10. 23种经典设计模式-23-代理模式扩展-cglib
程序员文章站
2022-06-04 23:18:01
...
1. cglib 代理
- Cglib 代理也叫子类代理, 它是在内存中创建一个子类对象,从而实现对目标对象的功能扩展.
- Cglib 的底层是通过字节码处理框架ASM来转换字节码并生成新的子类
1.1 注意事项
- 代理的类不能使用final 修饰
- 不能代理目标对象中被final 或 static 的方法, 因为cglib是通过拦截器机制实现的.
1.2 cglib 应用
- cglib 被广泛用于各种Aop框架中, 如Sring的AOP 机制.
- Spring AOP 动态代理实现逻辑:
- 如果目标对象实现了接口, 那么使用JDK动态代理方式创建代理对象
- 如果目标对象没有实现任何接口,那么使用cglib方式创建代理对象
2. cglib 动态代理
2.1 测试类图
- MethodInvoker: 是cglib包下的接口, net.sf.cglib.proxy.MethodInterceptor
- CglibProxy: 代理方法处理器, 类似于jdk动态代理的InvocationHandler
[外链图片转存失败(img-025VRukv-1566895017143)(https://raw.githubusercontent.com/zongf0504/blog-images/master/images/design-parttern/ldp-proxy-02.png)]
2.2 引入cglib 依赖
使用cglib 需要引入cglib 和 asm 包, 需要注意的是cglib 和 asm 包具有兼容性. 笔者用cglib3.0 测试有冲突, 所以切换回了cglib 2.2
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>2.2</version>
</dependency>
<dependency>
<groupId>asm</groupId>
<artifactId>asm-commons</artifactId>
<version>3.3.1</version>
</dependency>
2.3 被代理类
定义一个不实现任何接口的业务类
public class Hello {
public void sayHello() {
System.out.println("do method --> " + getClass().getName() + ".sayHello");
}
public void sayHi() {
System.out.println("do method --> " + getClass().getName() + ".sayHi");
}
}
2.3 cglib 动态方法处理器
和JDK动态代理类似, cglib 也需要实现一个目标方法代理处理器:
- 实现接口MethodInterceptor, 并实现其intercept 方法
- 提供获取动态代理对象的方法getProxyInstance(), 返回代理对象
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
public class CglibProxy implements MethodInterceptor {
// 被代理对象
private Object target;
public CglibProxy(Object object) {
this.target = object;
}
// 获取动态代理对象
public <T> T getProxyInstance() {
// 1. 创建工具类
Enhancer enhancer = new Enhancer();
// 2. 设置父类
enhancer.setSuperclass(target.getClass());
// 3. 设置回调函数
enhancer.setCallback(this);
// 4. 创建子类对象, 即代理对象
return (T) enhancer.create();
}
@Override
public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
// 执行目标方法前,可做一些预处理操作
System.out.println("前置通知...");
// 执行目标方法
Object result = method.invoke(target, args);
// 执行目标方法后, 可做一些清理工作
System.out.println("后置通知...");
// 返回结果
return result;
}
}
2.4 测试
@Test
public void test_cglib(){
// 创建被代理对象
Hello targetService = new Hello();
// 创建代理对象
Hello proxy = new CglibProxy(targetService).getProxyInstance();
// 执行请求
proxy.sayHello();
System.out.println("\n************************************************\n");
proxy.sayHi();
}
2.5 测试输出
前置通知...
do method --> org.zongf.learn.design.pattern.proxy.Hello.sayHello
后置通知...
************************************************
前置通知...
do method --> org.zongf.learn.design.pattern.proxy.Hello.sayHi
后置通知...
上一篇: 创建型模式