Spring 将带有 @Aspect
注解的类转换为 AOP 切面的过程,主要涉及以下几个步骤:
1. 启用 AOP 支持:
- XML 配置: 使用
<aop:aspectj-autoproxy/>
元素。 - JavaConfig: 使用
@EnableAspectJAutoProxy
注解。 - SpringBoot: 自动启用,无需额外配置(除非需要自定义)。
2. 组件扫描:
- Spring 容器启动时,会扫描指定的包(通过
<context:component-scan>
、@ComponentScan
或 JavaConfig 中的@Configuration
类),查找带有@Component
、@Service
、@Repository
、@Controller
等注解的类,以及带有@Aspect
注解的类。 - 找到
@Aspect
注解的类后,Spring 会将其注册为一个 BeanDefinition。
3. 解析 @Aspect
类:
- Spring 使用
AspectJAutoProxyCreator
(一个BeanPostProcessor
)来处理@Aspect
类。 AspectJAutoProxyCreator
会检查容器中所有的 Bean,找出带有@Aspect
注解的 Bean。- 对于每个
@Aspect
Bean,AspectJAutoProxyCreator
会使用反射机制读取该类中的所有方法,并检查这些方法上是否有 AspectJ 提供的切点注解:@Pointcut
:定义切点表达式。@Before
:前置通知。@After
:后置通知。@AfterReturning
:返回通知。@AfterThrowing
:异常通知。@Around
:环绕通知。
- 根据这些注解,
AspectJAutoProxyCreator
会将@Aspect
类解析成一个或多个Advisor
对象。Advisor
是 Spring AOP 中的一个核心接口,它包含了切点(Pointcut)和通知(Advice)。- 一个
@Aspect
类可以包含多个切点和通知,因此可能会被解析成多个Advisor
。
4. 创建 Advisor:
- 对于每个切点注解(例如
@Before
、@After
等),AspectJAutoProxyCreator
会创建一个对应的Advisor
对象。 Advisor
对象包含了:- Pointcut: 切点表达式,定义了哪些连接点(Join Point)需要被拦截。
- Advice: 通知,定义了在切点处需要执行的逻辑。
- Spring 内部会将这些 Advisor 存储起来,以便后续为目标对象创建代理。
5. 创建代理对象:
- 当 Spring 容器创建其他 Bean(目标对象)时,
AspectJAutoProxyCreator
会检查这些 Bean 是否匹配任何Advisor
中的切点。 - 如果目标对象匹配某个切点,
AspectJAutoProxyCreator
会为目标对象创建一个代理对象(使用 JDK 动态代理或 CGLIB 动态代理)。 - 代理对象包含了目标对象和所有匹配的
Advisor
。
6. 方法调用:
- 当客户端调用代理对象的方法时,代理对象会根据
Advisor
中的通知类型,在调用目标方法前后执行相应的通知逻辑。
总结:
Spring 将 @Aspect
类转换为 AOP 切面的过程,主要是通过 AspectJAutoProxyCreator
这个 BeanPostProcessor
来实现的。AspectJAutoProxyCreator
会解析 @Aspect
类中的注解,将其转换为 Advisor
对象,并在创建目标对象时,根据切点匹配情况,为目标对象创建代理对象,从而实现 AOP 的功能。
关键类和接口:
@Aspect
: AspectJ 提供的注解,用于标记一个类为切面。@Pointcut
、@Before
、@After
、@AfterReturning
、@AfterThrowing
、@Around
: AspectJ 提供的注解,用于定义切点和通知。AspectJAutoProxyCreator
: Spring AOP 中的一个关键类,实现了BeanPostProcessor
接口,负责解析@Aspect
类,创建Advisor
,并为目标对象创建代理。Advisor
: Spring AOP 中的一个核心接口,包含了切点(Pointcut)和通知(Advice)。Pointcut
: Spring AOP 中的一个接口,用于定义切点表达式。Advice
: Spring AOP 中的一个接口,用于定义通知(增强逻辑)。
Spring AOP 实现了声明式的面向切面编程,我们在开发时只需要使用注解来定义切面、切点和通知,Spring 会自动完成底层的代理创建和通知织入工作。