一、前言
根据创建代理类的时间点,又可以分为静态代理和动态代理。
了解代理模式
定义:代理类和被代理类实现共同的接口(或继承),代理类中存有指向被代理类的索引,实际执行时通过调用代理类的方法、实际执行的是被代理类的方法。
作用:代理模式最主要的就是有一个公共接口或者父类,一个具体的类,一个代理类,代理类持有具体类的实例,代为执行具体类实例方法。代理模式就是在访问实际对象时引入一定程度的间接性,因为这种间接性,可以附加多种用途。
常见实现:Spring的AOP实现原理就是用到了代理模式。
被代理类
一般指我们的业务类,实现具体业务方法的类。
代理类
一般指对业务类进行“增强”的类,实现一些不影响主业务的增强方法,如添加日志等功能。
结构图
二、静态代理
定义:由程序员创建或特定工具自动生成源代码,也就是在编译时就已经将接口,被代理类,代理类等确定下来。在程序运行之前,代理类的.class文件就已经生成。
场景分析
场景:假如一个班的同学要向老师交班费,但是都是通过班长把自己的钱转交给老师。这里,班长就是代理学生上交班费,班长就是学生的代理。
代码思路:首先,我们创建一个IStudent接口。这个接口就是学生(被代理类),和班长(代理类)的公共接口,他们都有上交班费的行为。这样,学生上交班费就可以让班长来代理执行。
代码实现
使用代理类的好处
三、动态代理
定义:代理类在程序运行时才被创建的代理方式被成为动态代理。
优势:可以很方便的对代理类的方法进行统一的处理,而不用修改每个代理类中的方法。
代码实现
四、动态代理源码解析
Proxy.newProxyInstance是Proxy的静态方法,代码并不难理解,除去权限相关的代码外,就剩下两步:
- 1,获取代理类对象(27行)
- 2,利用反射技术实例化代理类,并返回实例化对象(52行)
详解查看参考文章的第一篇:JAVA设计模式-动态代理(Proxy)源码分析【强推👍】
五、JDK动态代理和CGLIB代理的区别
区别
- JDK动态代理只能对实现了接口的类生成代理,而不能针对普通类【针对接口】
- CGLIB是针对类实现代理,主要是对指定的类生成一个子类,覆盖其中的方法(继承)【针对父类】
选择依据
- (1)当Bean实现接口时,Spring就会用JDK的动态代理
- (2)当Bean没有实现接口时,Spring使用CGlib是实现
- (3)可以强制使用CGlib(在spring配置中加入<aop:aspectj-autoproxy proxy-target-class="true"/>)
效能区别【作了解即可】
- (1)使用CGLib实现动态代理,CGLib底层采用ASM字节码生成框架,使用字节码技术生成代理类,比使用Java反射效率要高。唯一需要注意的是,CGLib不能对声明为final的方法进行代理,因为CGLib原理是动态生成被代理类的子类。
- (2)在对JDK动态代理与CGlib动态代理的代码实验中看,1W次执行下,JDK7及8的动态代理性能比CGlib要好20%左右。
参考文章:
JAVA设计模式-动态代理(Proxy)源码分析【强推👍】
Java动态代理实现与原理详细分析
动态代理:JDK动态代理和CGLIB代理的区别