代理模式
通过代理控制对象的访问,可以在这个对象调用方法之前、调用方法之后去处理/添加新的功能。(也就是AOP的实现)
代理在原有代码乃至原业务流程都不修改的情况下,直接在业务流程中切入新代码,增加新功能,这也和Spring的(面向切面编程)很相似
应用场景:SpringAOP、日志打印、异常处理、事务控制、权限控制等
-
静态代理
简单代理模式,是动态代理的理论基础。常见使用在代理模式/* 接口类 */ public class UserDao { public void Save(){ System.out.println("Save User Data"); } }/* 代理类 */ public class UserProxy extends UserDao{ private UserDao user; public UserProxy(UserDao user){ this.user = user; } public void Save(){ System.out.println("Open transaction"); this.user.Save(); System.out.println("close transaction"); } }/* 调用 */ public class Demo { public static void main(String[] args){ UserDao u = new UserDao(); UserProxy userProxy = new UserProxy(u); userProxy.Save(); } }- 缺点:每个需要代理的对象都需要自己重复编写代理
- 优点:但是可以面相实际对象或者是接口的方式实现代理
-
JKD动态代理
基于接口的动态代理技术·:利用拦截器(必须实现invocationHandler)加上反射机制生成一个代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理,从而实现方法增强/* 接口 */ public interface IUserDao { void save(); }/* 接口实现类 */ public class UserDaoImpl implements IUserDao { @Override public void save() { System.out.println("Save User Data"); } }/* 代理类 */ import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; //每次生成动态代理类对象时实现InvocationHandler接口的调用处理器对象 public class InvocationHandlerImpl implements InvocationHandler{ //业务类实现类对象,用来调用具体的方法 private Object target; //通过构造传入目标对象 public InvocationHandlerImpl(Object target){ this.target = target; } //动态代理实际运行得方法 @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("调用开始处理"); /* method.invoke(obj, args)方法是以反射的方式来创建对象的, 第一个参数obj是要创建的对象, 第二个args是构成方法的参数,决定创建对象使用哪个构造函数 */ Object result = method.invoke(target, args); System.out.println("调用结束处理"); return result; } }/* 调用 */ public class Test { public static void main(String[] args){ //被代理对象 IUserDao uerDaoImpl = new UserDaoImpl(); InvocationHandlerImpl invocationHandlerImpl = new InvocationHandlerImpl(uerDaoImpl); //类加载器 ClassLoader loader = uerDaoImpl.getClass().getClassLoader(); Class<?>[] interfaces = uerDaoImpl.getClass().getInterfaces(); //主要装载器、一组接口及调用处理动态代理实例 IUserDao newProxyInstance = (IUserDao)Proxy.newProxyInstance(loader, interfaces, invocationHandlerImpl); newProxyInstance.save(); } }- 缺点:必须是面向接口,目标业务类必须实现接口
- 优点:不用关心代理类,只需要在运行阶段才指定代理哪一个对象

浙公网安备 33010602011771号