代理即为访问对象添加一层控制层,使其间接化,控制层可以为对象访问添加操作属性。
CGLib:Code Generation Library。
使用JDK创建代理有一个限制,即它要求被代理对象实现了某一个或某些接口,如果被代理对象没有实现接口,可以使用CGLib实现动态代理~
CGLib采用底层的字节码技术,可以为一个类创建子类,在子类中采用方法拦截的技术拦截所有父类方法的调用并织入横切逻辑。
maven坐标:
<!-- https://mvnrepository.com/artifact/cglib/cglib -->
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>3.2.4</version>
</dependency>
- 基于ASM(java字节码操作码)的高性能代码生成包
- 被许多AOP框架使用
- 区别于JDK动态代理,cglib不需要被代理对象实现接口。
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 Enhancer enhancer = new Enhancer();
public Object createProxyInstance(Class clazz) {
//设置需要创建子类的类
enhancer.setSuperclass(clazz);
enhancer.setCallback(this);
//使用字节码技术动态创建子类实例
return enhancer.create();
}
/**
* 拦截父类所有方法的调用
* @param obj 目标类的实例
* @param method 目标类方法的反射对象
* @param args 方法参数
* @param proxy 代理对象
* @return
* @throws Throwable
*/
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
System.out.println("执行实例方法前的横切逻辑");
Object result = proxy.invokeSuper(obj, args);
System.out.println("执行实例方法后的横切逻辑");
return result;
}
}
测试
public class Client {
public static void main(String[] args) {
//创建代理对象
RealSubject subject = (RealSubject) new CglibProxy().createProxyInstance(RealSubject.class);
//执行方法(使用的是代理对象)
//生成代理对象之后,调用request方法,subject只是一个代理对象
subject.request();
System.out.println("代理类:" + subject);
}
}
执行结果:
执行实例方法前的横切逻辑
From real subject.
执行实例方法后的横切逻辑
代理类:RealSubject$$EnhancerByCGLIB$$564b4e3e@32a1bec0
RealSubject$$EnhancerByCGLIB$$564b4e3e@32a1bec0就是CGLib为RealSubject动态创建的代理子类
因为CGLib使用动态创建子类的方式生成代理对象,所以不能对目标类中的final或private方法进行代理!