
在 Java 里动态代理主要分接口动态代理 和 类动态代理。因为它的代理类都是动态创建的所以名字里会带上 “动态”。官网的有些地方叫 “代理”也有些地方叫 “动态代理”。都是一个意思。1、接口动态代理这是 jdk 直接支持的能力。内在的原理是框架会动态生成目标接口的一个代理类即接口的实现类并返回使用者在调用接口的函数时实际上调用的是这个代理类的函数而代理类又把数据转给了调用处理器接口。而整个过程的感受是调用目标接口最终到了 InvocationHandler 的实现类上//1. 定义目标接口 public interface UserService{ void addUser(int userId, String userName); } // //2. 通过JDK接口获得一个代理实例 UserService userService Proxy.getProxy(UserService.class, new InvocationHandlerImpl()); //生成的 UserService 代理类差不多是这个样子 public class UserService$Proxy implements UserService{ final InvocationHandler handler; final Method addUser2; //示意一下别太计较它哪来的 public UserService$Proxy(InvocationHandler handler){ this.handler handler; } Override public void void addUser(int userId, String userName){ handler.invoke(this, addUser2, new Object[](userId, userName)); } } //在调用 userService 时本质是调用 UserService$Proxy 的函数最终又是转发到 InvocationHandler 的实现类上。 // //3. 实现调用处理器接口 public class InvocationHandlerImpl implements InvocationHandler{ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable{ //... } }mark 一般接口动态代理是为了转发处理。/mark2、类动态代理类的动态代理略麻烦些且要借助字符码工具框架Solon 用的是 ASM。内在的原理倒是相差不大框架会动态生成目标类的一个代理类一个重写了所有函数的子类并返回使用者在调用目标类的函数时实际上调用的是这个代理类的函数而代理类又把数据转给了调用处理器接口。调用处理器在处理时会附加上别的处理。而整个过程的感受是调用目标类可以附加上很多拦截处理//1. 定义目标类 public class UserService{ public void addUser(int userId, String userName){ //.. } } // //2. 通过框架接口获得一个代理实例::注意这里的区别 UserService userService new UserService(); userService AsmProxy.getProxy(UserService.class, new AsmInvocationHandlerImpl(userService)); //生成的 UserService 代理类差不多是这个样子 public class UserService$AsmProxy extends UserService{ final AsmInvocationHandler handler; final Method addUser2; //示意一下别太计较它哪来的 public UserService$Proxy(AsmInvocationHandler handler){ this.handler handler; } Override public void void addUser(int userId, String userName){ handler.invoke(this, addUser2, new Object[](userId, userName)); } } //本质还是调用 UserService$AsmProxy 的函数最终也是转发到 AsmInvocationHandler 的实现类上。 // //3. 实现调用处理器接口 public class AsmInvocationHandlerImpl implements AsmInvocationHandler{ //::注意这里的区别 final Object target; public AsmInvocationHandlerImpl(Object target){ this.target target; } public Object invoke(Object proxy, Method method, Object[] args) throws Throwable{ //::注意这里的区别 MethodWrap methodWrap MethodWrap.get(method); //MethodWrap 内部对各种拦截器做了封装处理 methodWrap.invoke(target, args); } }mark 一般类动态代理是为了拦截并附加处理。/mark3、关于 Solon 的类代理情况与 “函数环绕拦截”对 Solon 来讲只有一个函数反射后再经 MethodWrap 执行的就是被代理了。所有的 “函数环绕拦截” 处理就封装在 MethodWrap 里面。Controller、Remoting 注解的类这两个注解类没有 ASM 的类代码但是它们的 Method 会转为 MethodWrap 并包装成 Action 注册到路由器。即它们是经 MethodWrap 再调用的。所以它们有代理能力支持 “函数环绕拦截”。Service、Dao、Repository 注解的类这三个注解来自 solon.aspect 插件包它们注解的类都会被 ASM 代理。跟上面原理分析的一样也支持 “函数环绕拦截”。有克制的拦截Solon 不支持表达式的随意拦截必须以注解为 “切点” 进行显示拦截。mark 所以 Solon 不用为所有的 Bean 增加代理能力按需添加即可 /mark。