代码:
UserDao.java
public interface UserDao { void add(); }UserDaoImpl.java
public class UserDaoImpl implements UserDao { @Override public void add() { System.out.println("模拟,添加用户!"); } }UserDaoProxy.java
public class UserDaoProxy implements UserDao { // 授权 private UserDao ud = new UserDaoImpl(); @Override public void add() { System.out.println("代理操作:开启事务,为你遮风挡雨"); ud.add(); System.out.println("代理操作:提交事务,为你保驾护航"); } }Test.java
public class Test { public static void main(String[] args) { UserDao ud = new UserDaoProxy(); ud.add(); } }总结:如果增加一个方法,除了实现类需要实现这个方法外,所有的代理类也要实现这个方法。增加了代码的维护成本。
静态代理就是有这样的问题,想解决这个问题,使用“动态代理”
UserDao.java
public interface UserDao { void add(); void findAll(); }UserDaoImpl.java
public class UserDaoImpl implements UserDao { @Override public void add() { System.out.println("模拟,保存用户!"); } @Override public void findAll() { System.out.println("查询所有用户"); } }UserDaoProxy.java
public class UserDaoProxy implements InvocationHandler { /// 目标,委托类 private Object target; // 授权 public Object getProxyInstance(Object object) { this.target = object; /* newProxyInstance(1,2,3); 1:目标对象使用的类加载器 2:目标对象实现的所有接口 3:代理对象 */ return Proxy.newProxyInstance(object.getClass().getClassLoader(), object.getClass().getInterfaces(), this); } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { String methodName = method.getName(); Object result = null; //查询方法不需要加事务,其他的增删改都需要事务管理 // findAll,findOneById if (methodName.indexOf("find") >= 0) { // 匹配查询方法 result = method.invoke(target, args); //执行目标方法 } else { //增删改 System.out.println("开始事务"); result = method.invoke(target, args);//执行目标方法 System.out.println("结束事务"); } return result; } }Test.java
public class Test { public static void main(String[] args) { // 目标对象 UserDao ud = new UserDaoImpl(); // 代理对象 UserDaoProxy proxy = new UserDaoProxy(); // 代理实例 UserDao proxyInstance = (UserDao) proxy.getProxyInstance(ud); proxyInstance.add(); System.out.println("----------------------------"); proxyInstance.findAll(); } }总结:使用JDK生成的动态代理的前提是目标对象必须有实现的接口,这里又引入一个新的问题,如果某个类没有实现接口,就不能用这种代理方式。Cglib代理就是解决这个问题的。
UserDao.java
public class UserDao { public void add(){ System.out.println("模拟,保存用户!"); } }UserDaoProxy.java
package proxy3; import org.springframework.cglib.proxy.Enhancer; import org.springframework.cglib.proxy.MethodInterceptor; import org.springframework.cglib.proxy.MethodProxy; import java.lang.reflect.Method; /** * @BelongsProject: spring2 * @Author: GuoAn.Sun * @CreateTime: 2020-06-29 12:12 * @Description: ${Description} */ public class UserDaoProxy implements MethodInterceptor { //目标对象 private Object target; //获得代理对象 public Object getInstance( Object target){ this.target = target; //创建增强对象 Enhancer enhancer = new Enhancer(); //设置增强的父类 enhancer.setSuperclass(this.target.getClass()); //设置回调方法 enhancer.setCallback(this); //返回代理对象 return enhancer.create(); } // 回调方法 @Override public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { System.out.println("事务开始"); Object result = methodProxy.invoke(target, objects); System.out.println("事务结束"); return result; } }Test.java
public class Test { public static void main(String[] args) { //目标 UserDao ud = new UserDao(); //代理 UserDaoProxy proxy = new UserDaoProxy(); UserDao dao = (UserDao) proxy.getInstance(ud); dao.add(); } }