CGlib的动态代理
个人笔记:
总结来自 B站: 孙哥说Spring5
danchu的CSDN: CGLIB(Code Generation Library)详解
1. JDK动态代理的不足
JDK动态代理需要:
1. 接口
2. 原始类
3. 代理类 (与原始类同接口)
当遇到没有原始类没有实现任何接口的的情况, 则无法实现JDK动态代理
2. CGlib是什么
CGLIB(Code Generator Library)是一个强大的、高性能的代码生成库。其被广泛应用于AOP框架(Spring、dynaop)中,用以提供方法拦截操作。Hibernate作为一个比较受欢迎的ORM框架,同样使用CGLIB来代理单端(多对一和一对一)关联(延迟提取集合使用的另一种机制)。
CGLIB作为一个开源项目,其代码托管在github,地址为:https://github.com/cglib/cglib
3. CGib代理的原理
CDLIB 原理: 父子继承关系创建代理对象,原始类作为父类,代理类作为子类,这样既可以保证两者方法一致,同时在代理类中提供新的实现 (额外功能+原始方法)
public class UserServiceProxy extends UserServiceImpl{...}
CGLIB 底层: 使用字节码处理框架ASM,来转换字节码并生成新的类。不鼓励直接使用ASM,因为它要求你必须对JVM内部结构包括class文件的格式和指令集都很熟悉。
CGLIB 缺点: 对于final方法,无法进行代理。
4. 代码示例
package com.wyt.proxy;
/**
* @author Wyt
* @date 2020/10/22 20:13
*/
public interface UserService{
public void register(User user);
public boolean login(String name, String password);
}
package com.wyt.cglib;
import com.wyt.proxy.User;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
/**
* @author Wyt
* @date 2020/10/29 19:29
*/
public class TestCglib {
public static void main(String[] args) {
//1. 创建原始对象
UserService userService = new UserService();
/*
jdk方式:
Proxy.newProxyInstance(classloader, interface, invocation)
2. 通过cglib方式创建动态代理对象
Enhancer.serClassLoader() - 类加载器
Enhancer.setSuperClass() - 父类
Enhancer.serCallback() - 额外功能 --> MethodInterceptor(cglib)
Enhancer.create() --> 代理
*/
Enhancer enhancer = new Enhancer();
enhancer.setClassLoader(TestCglib.class.getClassLoader());
enhancer.setSuperclass(userService.getClass());
MethodInterceptor interceptor = new MethodInterceptor() {
//等同于 InvocationHandler --> invoke()
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("---cglib log---");
Object ret = method.invoke(userService, objects);
return ret;
}
};
enhancer.setCallback(interceptor);
UserService userServiceProxy = (UserService) enhancer.create();
userServiceProxy.login("wyt", "123456");
userServiceProxy.register(new User());
}
}
5. 总结
1. JDK动态代理 Proxy.newProxyInstance() 通过接口创建代理的实现类
2. Cglib动态代理 Enhancer 通过继承父类创建的代理类