在 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{
//...
}
}

一般,接口动态代理是为了:转发处理。

2、类动态代理

类的动态代理,略麻烦些,且要借助字符码工具框架(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);
}
}

一般,类动态代理是为了:拦截并附加处理。

3、关于 Solon 的类代理情况与“函数环绕拦截”

对 Solon 来讲,只有一个函数反射后再经 MethodWrap 执行的,就是被代理了。所有的“函数环绕拦截”处理就封装在 MethodWrap 里面。

  • @Controller、@Remoting 注解的类

这两个注解类,没有 ASM 的类代码,但是它们的 Method 会转为 MethodWrap ,并包装成 Action 注册到路由器。即它们是经 MethodWrap 再调用的。所以它们有代理能力,支持“函数环绕拦截”。

  • @Service、@Dao、@Repository 注解的类

这三个注解,来自 solon.aspect 插件包,它们注解的类,都会被 ASM 代理。跟上面原理分析的一样,也支持“函数环绕拦截”。

  • 有克制的拦截

Solon 不支持表达式的随意拦截,必须以注解为“切点”进行显示拦截。所以 Solon 不用为所有的 Bean 增加代理能力,按需添加即可。

最新文章

  1. 解决PKIX:unable to find valid certification path to requested target 的问题
  2. DOS 命令For精解示例
  3. .net单元测试初探
  4. mysql常用命令(1)
  5. Faster RNNLM (HS/NCE) toolkit
  6. mongodb unset/set 删除/增加字段
  7. Linux开机自启动
  8. win7远程连接ubuntu14.04.1桌面
  9. inform表单验证,正则表达式,用户名,身份证,密码,验证码
  10. c++ Qt向PHP接口POST文件流
  11. SkyWalking-netcore
  12. 2018-05-11-机器学习环境安装-I7-GTX960M-UBUNTU1804-CUDA90-CUDNN712-TF180-KERAS-GYM-ATARI-BOX2D
  13. 简单触发器实例insert
  14. hihocoder--1384 -- Genius ACM (倍增 归并)
  15. H5高德地图获取当前位置
  16. php面试题之一——HTML+CSS(基础部分)
  17. C# Asp.net 修改Ueditor编辑器上传图片保存路径
  18. 数据库 --- 4 多表查询 ,Navicat工具 , pymysql模块
  19. doctype和Quirks模式
  20. Alpha阶段敏捷冲刺(三)

热门文章

  1. NC-UClient下载安装应用详解
  2. navisworks2021保姆级下载安装教程
  3. 使用Opencv4和YOLOv4(XTDrone)训练模型遇到问题的记录(二)
  4. 【element】中el-row如何使内容垂直居中
  5. 一张VR图像帧的生命周期
  6. 07#Web 实战:实现 GitHub 个人主页项目拖拽排序
  7. 【Java SE】Day08 String类、static关键字、Arrays类、Math类
  8. Jvm上如何运行其他语言?JSR223规范最详细讲解
  9. 你的项目使用Optional了吗?
  10. C#关于委托的一些事,开发日志