在 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 开发之容器,八、动态代理的本质的更多相关文章

  1. mybatis开发Dao的Mapper动态代理方式

    1. 开发规范Mapper接口开发方法只需要程序员编写Mapper接口(相当于Dao接口),由Mybatis框架根据接口定义创建接口的动态代理对象,代理对象的方法体跟Dao原始方法中接口实现类的方法相 ...

  2. java开发必学知识:动态代理

    目录 1. 引言 2. 代理模式及静态代理 2.1 代理模式说明 2.2 静态代理 2.3 静态代理局限性 3. 动态代理 3.1 JAVA反射机制 3.2 JDK动态代理 3.2.1 JDK动态代理 ...

  3. 02.MyBatis在DAO层开发使用的Mapper动态代理方式

    在实际开发中,Mybatis作用于DAO层,那么Service层该如何调用Mybatis Mybatis鼓励使用Mapper动态代理的方式 Mapper接口开发方法只需要程序员编写Mapper接口(相 ...

  4. 【Mybtais】Mybatis 插件 Plugin开发(一)动态代理步步解析

    需求: 对原有系统中的方法进行'拦截',在方法执行的前后添加新的处理逻辑. 分析: 不是办法的办法就是,对原有的每个方法进行修改,添加上新的逻辑:如果需要拦截的方法比较少,选择此方法到是会节省成本.但 ...

  5. 深入理解Spring IoC容器和动态代理机制

    Deployment期间验证 实现一: <bean id="theTargetBean" class="..."/> <bean id=&qu ...

  6. MyBatis开发Dao的原始Dao开发和Mapper动态代理开发

    目录 咳咳...初学者看文字(Mapper接口开发四个规范)属实有点费劲,博主我就废了点劲做了如下图,方便理解: 原始Dao开发方式 1. 编写映射文件 3.编写Dao实现类 4.编写Dao测试 Ma ...

  7. 【Java EE 学习 50】【Spring学习第二天】【使用注解的DI实现】【spring中的继承】【动态代理伪hibernate实现】

    一.使用注解的DI实现 1.@Resource 使用该注解能够实现引用型属性的DI实现,该注解能够根据属性名和属性类型自动给属性赋值.一般使用@Resource(name="student& ...

  8. spring5——Aop的实现原理(动态代理)

    spring框架的核心之一AOP,面向切面编程是一种编程思想.我对于面向切面编程的理解是:可以让我们动态的控制程序的执行流程及执行结果.spring框架对AOP的实现是为了使业务逻辑之间实现分离,分离 ...

  9. .NET:动态代理的 “5 + 1” 模式

    背景 什么叫“动态代理”,代理模式我们都知道,动态代理就是动态生成的代理(采用Emit). 重量级的ORM和IOC产品离不开动态代理,作为开发人员,多数情况不用关注动态代理的内部实现机制,但是了解其一 ...

  10. java:Spring框架2(bean的作用域,静态工厂和实例工厂,自动装配,动态代理)

    1.bean的作用域,静态工厂和实例工厂: bean.xml: <?xml version="1.0" encoding="UTF-8"?> < ...

随机推荐

  1. 发布 .NET 7 MAUI / MAUI Blazor 应用到 Windows 应用商店

    .NET MAUI 目前仅允许发布 MSIX 包. 创建签名证书发布到本地传送门 [https://www.cnblogs.com/densen2014/p/16567384.html] 使用 Vis ...

  2. Nginx重写功能(rewrite与location)

    一.常用的Nginx 正则表达式 二.访问路由location 2.1location的分类 location 大致可以分为三类: 精准匹配:location = / {} 一般匹配:location ...

  3. 嵌入式-C语言基础:字符串拼接函数strcat

    #include<stdio.h> #include <string.h> //实现字符串拼接 char * mystrcat(char * dest,char * src) ...

  4. mindxdl--common--logger.go

    // Copyright (c) 2021. Huawei Technologies Co., Ltd. All rights reserved.// Package common the contr ...

  5. 注册IBMlinuxone并使用xshell登陆

    登陆地址:https://linuxone.cloud.marist.edu/#/login 注册地址:https://linuxone.cloud.marist.edu/#/register?fla ...

  6. Windows 下 OpenSSH 安装使用

    OpenSSH 是安全 Shell (SSH) 工具的开放源代码版本,Linux 及其他非 Windows 系统的管理员使用此类工具跨平台管理远程系统. OpenSSH 在 2018 年秋季已添加至 ...

  7. Kafka教程(三):原理及存储

    一.思维导图 1.实时更新连接 https://www.mubucm.com/doc/1GRE2U7qYuj 2.思维导图图片 二.具体内容   8.系统架构   架构推导   拓扑结构   多对多 ...

  8. 【Hadoop学习】中:HDFS、shell操作、客户端API操作、数据流、1NN、2NN原理、DataNode配置

    一.概述 1.背景.定义.使用场景(一次写入.不支持修改) 2.优(容错)缺点(延迟.不支持小文件.不支持修改) 3.组成架构 NameNode:Master,管理命名空间.配置策略 DataNode ...

  9. 干电池升压5V,功耗比较低

    干电池升压5V,功耗10uA PW5100干电池升压5V芯片 输出电容: 所以为了减小输出的纹波,需要比较大的输出电容值.但是输出电容过大,就会使得系统的 反应时间过慢,成本也会增加.所以建议使用一个 ...

  10. 编程思想的转变 软件开发目录规范 collections、time、datetime、 random模块

    目录 编程思想的转变 软件目录开发规范(重要) 内置模块:collections模块 简介 具名元组 namedtuple 实现二维坐标系 实现扑克牌 队列与堆栈 collection.deque() ...