Solon2 开发之容器,八、动态代理的本质
在 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 增加代理能力,按需添加即可。
Solon2 开发之容器,八、动态代理的本质的更多相关文章
- mybatis开发Dao的Mapper动态代理方式
1. 开发规范Mapper接口开发方法只需要程序员编写Mapper接口(相当于Dao接口),由Mybatis框架根据接口定义创建接口的动态代理对象,代理对象的方法体跟Dao原始方法中接口实现类的方法相 ...
- java开发必学知识:动态代理
目录 1. 引言 2. 代理模式及静态代理 2.1 代理模式说明 2.2 静态代理 2.3 静态代理局限性 3. 动态代理 3.1 JAVA反射机制 3.2 JDK动态代理 3.2.1 JDK动态代理 ...
- 02.MyBatis在DAO层开发使用的Mapper动态代理方式
在实际开发中,Mybatis作用于DAO层,那么Service层该如何调用Mybatis Mybatis鼓励使用Mapper动态代理的方式 Mapper接口开发方法只需要程序员编写Mapper接口(相 ...
- 【Mybtais】Mybatis 插件 Plugin开发(一)动态代理步步解析
需求: 对原有系统中的方法进行'拦截',在方法执行的前后添加新的处理逻辑. 分析: 不是办法的办法就是,对原有的每个方法进行修改,添加上新的逻辑:如果需要拦截的方法比较少,选择此方法到是会节省成本.但 ...
- 深入理解Spring IoC容器和动态代理机制
Deployment期间验证 实现一: <bean id="theTargetBean" class="..."/> <bean id=&qu ...
- MyBatis开发Dao的原始Dao开发和Mapper动态代理开发
目录 咳咳...初学者看文字(Mapper接口开发四个规范)属实有点费劲,博主我就废了点劲做了如下图,方便理解: 原始Dao开发方式 1. 编写映射文件 3.编写Dao实现类 4.编写Dao测试 Ma ...
- 【Java EE 学习 50】【Spring学习第二天】【使用注解的DI实现】【spring中的继承】【动态代理伪hibernate实现】
一.使用注解的DI实现 1.@Resource 使用该注解能够实现引用型属性的DI实现,该注解能够根据属性名和属性类型自动给属性赋值.一般使用@Resource(name="student& ...
- spring5——Aop的实现原理(动态代理)
spring框架的核心之一AOP,面向切面编程是一种编程思想.我对于面向切面编程的理解是:可以让我们动态的控制程序的执行流程及执行结果.spring框架对AOP的实现是为了使业务逻辑之间实现分离,分离 ...
- .NET:动态代理的 “5 + 1” 模式
背景 什么叫“动态代理”,代理模式我们都知道,动态代理就是动态生成的代理(采用Emit). 重量级的ORM和IOC产品离不开动态代理,作为开发人员,多数情况不用关注动态代理的内部实现机制,但是了解其一 ...
- java:Spring框架2(bean的作用域,静态工厂和实例工厂,自动装配,动态代理)
1.bean的作用域,静态工厂和实例工厂: bean.xml: <?xml version="1.0" encoding="UTF-8"?> < ...
随机推荐
- mindxdl---common--test_tools.go
// Copyright (c) 2021. Huawei Technologies Co., Ltd. All rights reserved.// Package common define co ...
- 【第6篇】AI语音测试简介
1.4 AI语音测试简介 AI语音测试是针对人工智能语音交互的测试,人工智能语音交互一般包含语音识别技术(ASR).自然语言处理技术(NLP)和语音合成技术(TTS)等3大部分,通俗地来讲AI语音测试 ...
- 在 Solidity 中 ++i 为什么比 i++ 更省 Gas?
前言 作为一个初学者,"在 Solidity 中 ++i 为什么比 i++ 更省 Gas?" 这个问题始终在每个寂静的深夜困扰着我.也曾在网上搜索过相关问题,但没有得到根本性的解答 ...
- vs2019中使用Git,新建项目时总提示部分项目位于解决方案文件夹外
最终还是用Git工具传上去的. 小伙子,用Git Bush或者Git CMD 和Git GUI传吧 我是用Git GUI. Git GUI汉化.感谢大佬 https://blog.csdn.net/u ...
- 【Advanced Installer】打包winfrom程序出现您没有任何数字签名的实用程序。请安装平台 SDK。错误
出现这个问题的原因是设置了磁铁,此功能只会在win8.1上有效.也就是开始菜单里面的磁铁图 只需要把这个删除掉就可以解决了
- linux sublime-text ctrl+shift+b 快捷键失效问题解决
解决办法 由于fcitx拦截了这个ctrl+shift+b 这个快捷键,所以取消即可 点击全局配置里面高级选项,然后找到ctrl+shift+b这个快捷键,点击后,按esc就可以将快捷键设置为空,不过 ...
- 批量删除多个相同格式内容的Excel表格的列
Sub Del_Col()Application.DisplayAlerts = FalseDim myFiles As StringDim myExcels As StringWith Applic ...
- 【ASP.NET Core】MVC控制器的各种自定义:IActionHttpMethodProvider 接口
IActionHttpMethodProvider 接口的结构很简单,实现该接口只要实现一个属性即可--HttpMethods.该属性是一个字符串序列. 这啥意思呢?这个字符串序列代表的就是受支持的 ...
- Java开发如何通过IoT边缘ModuleSDK进行协议转换?
摘要:使用ModuleSDK开发插件应用,接入其他协议设备(如HTTP请求数据),将其他协议的数据转化为MQTT协议JSON数据上报到IoTDA. 本文分享自华为云社区<[华为云IoTEdge开 ...
- uniapp input框聚焦时软键盘弹起整个页面上滑,固定页面不让上滑问题
根据需求,软键盘弹起时,不允许页面整体向上滑动 用到的属性是: :adjust-position="false" uni-app 软键盘顶起底部fixed定位的输入框 页面就不会 ...