文章内容
一、什么是代理模式
代理模式,为目标对象提供一个替身,以控制对这个对象的访问,进行附加功能增强,从而达到扩展目标对象的功能。比如:添加日志、事务控制、程序耗时等等。
二、代理模式角色
- 抽象角色:定义代理角色和真实角色的公共对外方法。
- 真实角色:实现抽象角色,定义真实角色所要实现的业务逻辑,供代理对象调用。
- 代理角色:实现抽象角色,是真实角色的代理,通过真实角色的业务逻辑方法来实现抽象方法,并可以增加前置和后置操作。
三、代理模式UML图

四、代理模式实现方式
- 静态代理:被代理对象(即目标对象)和代理对象需要实现共同的接口或继承共同的抽象类,同时代理对象需要关联目标对象。
- JDK动态代理:目标对象需要实现接口,代理对象不需要实现接口。利用JDK自带的Proxy类在运行时动态生成代理对象。
- Cglib动态代理:CGLIB代理也叫子类代理,在JVM运行时,在内存中动态的基于目标类创建一个子类对象,从而实现对目标对象的增强。CGLIB是通过使用字节码处理框架ASM来转换字节码并生成新的类。
五、静态代理优缺点
1、优点
- 避免了直接修改目标对象的功能,以代理模式对目标对象进行了功能扩展。
2、缺点
- 代理类需要与目标对象一一对应,可能会产生“类爆炸”,维护工作量巨大。
- 如果目标对象新增功能,代理类也要同步进行新增升级,可谓牵一发而动全身。
六、JDK动态代理Proxy类详解
JDK自带的代理类包路径java.lang.reflect.Proxy,调用静态方法newProxyInstance方法动态生成代理对象,该方法包括3个形参:
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) throws IllegalArgumentException
- ClassLoader loader: 指定目标对象所使用的类加载器,用于加载代理类。
- Class<?>[] interfaces: 目标对象实现的接口类,通过泛型确定类型,也是代理类实现的接口类。
- InvocationHandler h: 代理对象的调用处理程序,执行目标对象的方法,会把当前执行的目标对象 的方法作为参数传入。调用invoke方法进行增强业务处理。
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable;
- Object proxy:代理对象,在该方法中基本不用。
- Method method:目标对象的方法,对接口中的方法进行封装的method对象。
- Object[] args:调用目标对象方法的实际参数。
七、CGLIB动态代理
1、为啥要使用CGLIB
如果需要被代理的目标对象没有实现接口,这时就不能使用静态代理或JDK动态代理来实现了。这时,CGLIB就要登场了,它提供了一个功能强大、高性能的代码生成包,它可以为没有实现接口的普通类提供代理,弥补了JDK动态代理的不足。
2、使用CGLIB代理注意事项
- 被代理的目标对象不能为final
- 被代理的目标对象的方法不能被final、static修饰
3、引入CGLIB jar 包
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>2.2</version>
</dependency>
4、CGLIB 2个核心类
- net.sf.cglib.proxy.Enhancer:用于动态生成代理对象,作用类似JDK代理中的Proxy类。
- net.sf.cglib.proxy.MethodInterceptor:目标对象的拦截器,用于实现对目标对象的功能增强。
八、代理模式demo示例
1、Demo需求
以用户管理为例,对用户功能进行增强,添加方法入口日志和结束日志