Spring 中 aop 为什么需要 jdk 动态和 cglib 两种方式?是因为性能差异?还是什么原因?

只用cglib不行吗?他的效率更高哦

1 个回答

  • 无邪
    鸟随鸾凤飞腾远,人伴贤良品自高。
    ### Spring 中 AOP 为什么需要 JDK 动态代理和 CGLIB 两种方式? 在 Spring 框架中,AOP(Aspect-Oriented Programming,面向切面编程)有两种主要的代理方式:JDK 动态代理和 CGLIB。选择这两种代理方式的原因并不仅仅是性能差异,而是因为它们各自的特点和适用场景。以下是详细分析。 #### 1. JDK 动态代理 **特点**: - **基于接口**:JDK 动态代理只能代理实现了接口的类。它通过创建接口的代理实例,在运行时生成代理对象。 - **运行时生成**:JDK 动态代理是在运行时通过反射机制生成代理类。 **优点**: - **简单直接**:对于基于接口的服务,非常简单和直接。 - **低内存消耗**:生成的代理类较小,内存消耗低。 **缺点**: - **限制性**:只能代理接口,不能代理没有接口的类。 **示例代码**: ```java public interface Service { void perform(); } public class ServiceImpl implements Service { @Override public void perform() { System.out.println("Performing service..."); } } Service proxy = (Service) Proxy.newProxyInstance( Service.class.getClassLoader(), new Class[]{Service.class}, new InvocationHandler() { private final ServiceImpl service = new ServiceImpl(); @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("Before service..."); Object result = method.invoke(service, args); System.out.println("After service..."); return result; } } ); proxy.perform(); ``` #### 2. CGLIB 代理 **特点**: - **基于类**:CGLIB 代理是通过继承目标类来创建代理对象。因此,它可以代理没有接口的类。 - **字节码生成**:CGLIB 在运行时生成目标类的子类,通过字节码技术增强类的方法。 **优点**: - **灵活性**:可以代理没有接口的类,适用范围更广。 - **性能较高**:在某些情况下,CGLIB 代理的性能优于 JDK 动态代理。 **缺点**: - **内存消耗较高**:由于生成的子类会持有目标类的所有方法,因此内存消耗较高。 - **无法代理`final`类和方法**:由于 CGLIB 是通过生成子类实现代理,因此无法代理 `final` 类和方法。 **示例代码**: ```java public class Service { public void perform() { System.out.println("Performing service..."); } } Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(Service.class); enhancer.setCallback(new MethodInterceptor() { @Override public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable { System.out.println("Before service..."); Object result = proxy.invokeSuper(obj, args); System.out.println("After service..."); return result; } }); Service proxy = (Service) enhancer.create(); proxy.perform(); ``` ### 为什么需要两种代理方式? #### 1. 灵活性 Spring 选择同时支持 JDK 动态代理和 CGLIB 代理,主要是为了提供灵活性和兼容性。JDK 动态代理可以用于所有实现了接口的类,而 CGLIB 代理可以用于那些没有实现接口的类。 #### 2. 性能考虑 虽然 CGLIB 代理在某些情况下性能更好,但它的内存消耗较高,且无法代理 `final` 类和方法。因此,在可以使用 JDK 动态代理的情况下,优先选择 JDK 动态代理。 #### 3. 配置和使用上的考虑 Spring 默认使用 JDK 动态代理,如果目标类没有实现接口,Spring 会自动切换到使用 CGLIB 代理。这种策略使得开发者在大多数情况下不需要关心代理的具体实现方式,只需专注于业务逻辑。 ### 结论 Spring 中 AOP 支持 JDK 动态代理和 CGLIB 代理,两者各有优劣。选择这两种代理方式并不是单纯出于性能差异的考虑,而是为了提供更广泛的代理支持,确保灵活性和兼容性。在实际应用中,Spring 默认使用 JDK 动态代理,在必要时自动切换到 CGLIB 代理,以确保能够代理所有类型的类。
    编辑于 2024-01-03 09:51 •IP属地 北京
    举报
    评论
    收藏1