SpringBoot2为什么默认使用CGLib不再使用JDK动态代理
- CGLib和JDK动态代理对比
- 1. 不需要实现接口
- 2. 性能
- 3. 代理对象的创建
- 4. 调用方法
- 2. CGLib使用
CGLib和JDK动态代理对比
1. 不需要实现接口
JDK动态代理类要求目标类必须实现接口,而CGLib动态代理可以直接代理普通类(非接口),这为对那些没有接口的类进行代理提供了极大的灵活性.
2. 性能
CGlib动态代理比JDK动态代理更快,JDK动态代理是通过反射来实现的,而CGLib动态代理是使用字节码生成技术,直接操作字节码,因此CGLib性能更高.
3. 代理对象的创建
JDK动态代理只能代理实现了接口的类,它是通过Proxy类和InvocationHandler接口来创建代理对象.而CGLib动态代理可以代理任意类(final修饰的类和fina修饰的方法除外),它是通过Enhancer类来创建代理对象,无需接口.
4. 调用方法
JDK动态代理对代理方法的调用是通过InvocationHandler来转发的,而CGLib动态代理是对代理方法通过FastClass机制来直接调用目标方法的,这也是CGLib性能较高的原因之一.
2. CGLib使用
- 引入CGLib依赖
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>3.3.0</version>
</dependency>
- 目标类
@Service
@RequiredArgsConstructor
public class UserService {
private final UserMapper userMapper;
public User findById(Long id){
System.out.println("findById()...");
return userMapper.findById(id);
}
}
- 使用
@Test
public void cglibCase(){
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(UserService.class);
enhancer.setCallback(new MethodInterceptor() {
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
System.out.println("前置增强");
Object o = proxy.invokeSuper(obj, args);
System.out.println("后置增强");
return o;
}
});
UserService userService = (UserService) enhancer.create(new Class[]{UserMapper.class},new Object[]{userMapper});
System.out.println(userService.findById(2L));
}
由于目标类没有空参构造方法,使用Enhancer中create()需要传入代理方法的参数类型和参数,不然会报一下错误