当前位置:  首页>> 技术小册>> Spring AOP 编程思想(上)

章节:AopProxy工厂接口与实现

在深入探讨Spring AOP(面向切面编程)的核心机制时,AopProxy工厂接口及其实现扮演着至关重要的角色。这一章节将详细解析AopProxy接口的设计思想、关键方法、以及Spring框架中几种主要的AopProxy实现方式,帮助读者深入理解Spring AOP背后的动态代理机制。

一、AopProxy接口概述

AopProxy是Spring AOP框架中的一个核心接口,它封装了对目标对象(被代理对象)的代理逻辑。通过代理,AOP能够在不修改源代码的情况下,为目标对象添加额外的行为(即切面中的增强逻辑)。AopProxy接口定义了生成代理对象的基本框架,允许Spring根据不同的代理策略(如JDK动态代理或CGLIB代理)来创建代理实例。

关键方法
  • Object getProxy(): 返回一个代理对象实例。这是AopProxy接口中最核心的方法,它负责生成并返回具体的代理对象。
  • Object getProxy(ClassLoader classLoader): 类似于getProxy(),但允许指定类加载器。这对于在特定类加载器环境下创建代理对象非常有用。
  • boolean isProxyTargetClass(): 指示是否代理目标类本身,而非其接口。这是区分JDK动态代理和CGLIB代理的重要标志之一。
  • AdvisedSupport getAdvised(): 返回与当前AopProxy关联的AdvisedSupport对象,该对象包含了代理对象所需的所有配置信息,如增强器(Advisor)列表、目标对象等。

二、AopProxy的实现方式

在Spring AOP中,AopProxy接口有多个实现,主要包括基于JDK动态代理的JdkDynamicAopProxy和基于CGLIB的CglibAopProxy。每种实现方式都有其适用场景和优缺点。

1. JdkDynamicAopProxy

JdkDynamicAopProxyAopProxy的一个实现,它利用JDK自带的动态代理机制(java.lang.reflect.Proxy)来创建代理对象。JDK动态代理要求目标对象必须实现至少一个接口,因为它只能代理接口。

核心逻辑

  • JdkDynamicAopProxy通过Proxy.newProxyInstance()方法创建代理对象。
  • 代理对象的所有方法调用都会通过InvocationHandler接口的invoke()方法转发给JdkDynamicAopProxy实例处理。
  • invoke()方法中,JdkDynamicAopProxy会根据方法签名和增强器配置,决定是否应用额外的增强逻辑(如前置通知、后置通知等),并最终调用目标对象的方法。

优点

  • 无需依赖第三方库,JDK自带支持。
  • 代理对象性能较高,因为JDK动态代理是基于Java反射API实现的。

缺点

  • 只能代理实现了接口的类。
2. CglibAopProxy

对于没有实现接口的类,Spring AOP提供了基于CGLIB的代理实现——CglibAopProxy。CGLIB是一个强大的、高性能的代码生成库,它可以在运行时动态地生成目标类的子类,从而实现对非接口类的代理。

核心逻辑

  • CglibAopProxy使用CGLIB的Enhancer类来生成目标类的子类。
  • 在子类中,CGLIB会拦截所有的方法调用,并将它们转发给CglibAopProxy实例的intercept()方法处理。
  • intercept()方法类似于JdkDynamicAopProxyinvoke()方法,负责根据增强器配置决定是否应用额外的增强逻辑,并调用目标对象的实际方法。

优点

  • 能够代理没有实现接口的类。
  • 提供了更多的灵活性,因为可以覆盖或增强非final方法和final类中的构造函数。

缺点

  • 依赖于第三方库(CGLIB)。
  • 相对于JDK动态代理,CGLIB生成的代理对象性能略低,因为它需要生成和加载额外的类文件。

三、AopProxy工厂的实现与选择

在Spring AOP中,AopProxyFactory负责根据目标对象的特性(是否实现了接口)和配置(如是否强制使用CGLIB代理)来选择合适的AopProxy实现。

选择逻辑

  • 如果目标对象实现了至少一个接口,并且没有强制使用CGLIB代理的配置,则默认使用JdkDynamicAopProxy
  • 如果目标对象没有实现任何接口,或者配置了强制使用CGLIB代理,则使用CglibAopProxy

实现细节

  • DefaultAopProxyFactoryAopProxyFactory的一个常见实现,它包含了上述的选择逻辑。
  • 开发者可以通过配置Spring的aop:config元素或相关注解来指定代理策略,如proxy-target-class="true"将强制使用CGLIB代理。

四、总结

AopProxy工厂接口及其实现是Spring AOP框架中动态代理机制的核心。通过JdkDynamicAopProxyCglibAopProxy两种实现,Spring AOP能够灵活地处理不同情况下的代理需求,为开发者提供了强大的面向切面编程能力。理解AopProxy的设计和实现,有助于我们更深入地掌握Spring AOP的工作原理,从而更加高效地利用这一强大的编程范式。

在实际开发中,根据目标对象的特性和性能要求选择合适的代理策略是非常重要的。例如,对于性能敏感且实现了接口的类,建议使用JDK动态代理;而对于需要代理没有接口的类,或者希望获得更多灵活性的场景,则可以考虑使用CGLIB代理。