1. jdk 与 cglib 动态代理对比
1.1 都会将生成的代理类缓存起来,先从缓存中获取,没有才生成,得到代理类后,生成代理类的实例
1.2 jdk动态代理只能生成接口的代理类,cglib可以生成普通类的代理类,但不能生成final类的代理类
1.3 cglib代理类比jdk代理类占用更多的内存空间(通过为同一个实现类生成代理类,然后对比输出的class)
1.4 cglib代理类继承被代理类,jdk代理类继承Proxy并实现被代理类实现的接口
2. jdk动态代理使用方式及流程分析
2.1 需要用到类:Proxy, InvocationHandler
Proxy: 负责代理类及其实例的创建, 其字段InvocationHandler h 用来调用被代理对象对应的方法,
生成的代理类继承Proxy,代理类通过super.h.invoke(Object proxy, Method method, Object[] args)
调用被代理对象的对应方法;
代理类由 ProxyBuilder.defineProxyClass(Module m, List<Class<?>> interfaces) 调用
ProxyGenerator.generateProxyClass(final String name, Class<?>[] interfaces, int accessFlags)
生成
InvocationHandler: 保存被代理类实例的引用
2.2 code
DailyLife target = new ConcreteDailyLife();
DailyLife proxy = (DailyLife) Proxy.newProxyInstance(
JdkProxyDemo.class.getClassLoader(), // the class loader to define the proxy class
ConcreteDailyLife.class.getInterfaces(), // the list of interfaces for the proxy class to implement
new MyInvocationHandler(target)); // the invocation handler to dispatch method invocations to
proxy.eat();
proxy.sleep();
2.3 写出生成的代理类到磁盘文件
byte[] concreteDailyLife = MyProxyGenerator.generateProxyClass(
"JdkConcreteDailyLifeProxy",
ConcreteDailyLife.class.getInterfaces());
FileUtil.write("C:\\Users\\output\\JdkConcreteDailyLifeProxy.class", concreteDailyLife);
3. cglib使用方式及流程分析
3.1 添加maven依赖
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>3.3.0</version>
</dependency>
3.2 需要用到类:Enhancer, MethodInterceptor, Callback
3.3 code
public class CglibDemo {
public static void main(String[] args) throws Exception {
CustomerService target = new CustomerService();
Callback[] callbacks = new Callback[] {
new RefundInterceptor(target), // RefundInterceptor实现 MethodInterceptor
new CommonInterceptor(target) }; // CommandInterceptor MethodInterceptor
// 构造Enhancer: 初始化 EnhancerKey KEY_FACTORY,通过调用 AbstractClassGenerator.create(Object key)
// 创建 EnhancerKey 的实例;
Enhancer enhancer = new Enhancer();
// 设置被代理类为父类
enhancer.setSuperclass(CustomerService.class);
// 设置回调
enhancer.setCallbacks(callbacks);
// 设置回调过滤器
enhancer.setCallbackFilter(method -> {
// refund 方法调用 RefundInterceptor,其他方法调用 CommonInterceptor
if (method.getName().endsWith("refund")) {
return 0; // 0 对应callbacks里面的第一个Callback,即 RefundInterceptor
}
return 1; // 1 对应callbacks里面的第二个Callback,即 CommonInterceptor
});
// 创建代理实例, 流程说明参考 "3.4 cglib 创建代理实例执行流程"
CustomerService proxy = (CustomerService) enhancer.create();
proxy.refund();
proxy.pack();
}
}
3.4 cglib 创建代理实例执行流程
step1: Enhancer:: create >> createHelper
step2: AbstractClassGenerator:: create
step3: 使用 AbstractClassGenerator$ClassLoaderData, LoadingCache 获取缓存
step4: 构建 FutureTask, 通过 FutureTask 异步创建代理类实例
step5: Enhancer::generate
step6: AbstractClassGenerator::generate
step7: DefaultGeneratorStrategy::generate(ClassGenerator cg)
step8: Enhancer::generateClass(ClassVisitor v)
step9: AbstractClassGenerator::generate
step10: 返回创建好的代理类实例
3.5 写出生成的代理类到磁盘文件
// 需要创建代理类实例成功后才能写出代理类到磁盘
CustomerService proxy = (CustomerService) enhancer.create();
// 代理类实例已生成是以下输出的前提条件
FileUtil.write(
"C:\\Users\\output\\CglibCustomerServiceProxy.class",
DefaultGeneratorStrategy.INSTANCE.generate(enhancer));