SpringBoot2为什么默认使用CGLib不再使用JDK动态代理

SpringBoot2为什么默认使用CGLib不再使用JDK动态代理

    • CGLib和JDK动态代理对比
      • 1. 不需要实现接口
      • 2. 性能
      • 3. 代理对象的创建
      • 4. 调用方法
    • 2. CGLib使用

SpringBoot2为什么默认使用CGLib不再使用JDK动态代理_第1张图片

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>cglibgroupId>
     <artifactId>cglibartifactId>
     <version>3.3.0version>
 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));
    }

SpringBoot2为什么默认使用CGLib不再使用JDK动态代理_第2张图片

由于目标类没有空参构造方法,使用Enhancer中create()需要传入代理方法的参数类型和参数,不然会报一下错误
SpringBoot2为什么默认使用CGLib不再使用JDK动态代理_第3张图片

你可能感兴趣的:(java,开发语言,spring,boot,后端)