Spring Boot 中 AOP 的自动装配原理

发布于:2025-05-08 ⋅ 阅读:(22) ⋅ 点赞:(0)

在 Spring Boot 中,AOP 的自动装配 是通过 @EnableAutoConfigurationAopAutoConfiguration 自动完成的。开发者无需手动配置 @EnableAspectJAutoProxyAnnotationAwareAspectJAutoProxyCreator,Spring Boot 会根据项目依赖和配置自动完成这些操作。


🧠 一、Spring Boot AOP 自动装配的核心机制

✅ 1. 自动装配入口:@SpringBootApplication

Spring Boot 的启动类通常使用 @SpringBootApplication 注解,它组合了以下三个核心注解:

@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan

其中 @EnableAutoConfiguration 是自动装配的入口,它会导入 AutoConfigurationImportSelector,并加载所有符合条件的自动配置类。


✅ 2. AOP 自动配置类:AopAutoConfiguration

Spring Boot 提供了 AopAutoConfiguration 类,用于自动配置 AOP 相关的组件。

@Configuration(proxyBeanMethods = false)
@ConditionalOnProperty(prefix = "spring.aop", name = "auto", havingValue = "true", matchIfMissing = true)
public class AopAutoConfiguration {

    @Configuration(proxyBeanMethods = false)
    @ConditionalOnClass(Advice.class)
    static class AspectJAutoProxyingConfiguration {

        @Bean
        @ConditionalOnMissingBean(AnnotationAwareAspectJAutoProxyCreator.class)
        public AnnotationAwareAspectJAutoProxyCreator aspectJAutoProxyCreator() {
            AnnotationAwareAspectJAutoProxyCreator proxyCreator = new AnnotationAwareAspectJAutoProxyCreator();
            proxyCreator.setProxyTargetClass(true); // 默认使用 CGLIB 代理
            return proxyCreator;
        }
    }

    @Configuration(proxyBeanMethods = false)
    @ConditionalOnMissingClass("org.aspectj.weaver.Advice")
    static class NoAspectJAutoProxyingConfiguration {
        // 如果没有 AspectJ 依赖,则不启用 AOP 自动代理
    }
}

📌 关键点

  • 只有项目中存在 org.aspectj.weaver.Advice 类(即引入了 aspectjweaver 依赖),才会启用 AOP 自动代理。
  • 默认使用 CGLIB 代理(proxyTargetClass = true)。

🔄 二、AOP 自动装配流程详解

✅ 1:启用自动装配(@EnableAutoConfiguration

@SpringBootApplication
public class MyApplication {
    public static void main(String[] args) {
        SpringApplication.run(MyApplication.class, args);
    }
}
  • @SpringBootApplication 包含 @EnableAutoConfiguration
  • @EnableAutoConfiguration 会导入 AutoConfigurationImportSelector

✅ 2:加载 AopAutoConfiguration 自动配置类

Spring Boot 会扫描 spring-boot-autoconfigure 模块下的 META-INF/spring.factories 文件,加载所有自动配置类,包括:

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration

✅ 3:判断是否启用 AOP 自动代理

@ConditionalOnClass(Advice.class)
  • 如果项目中存在 Advice 类(即引入了 aspectjweaver 依赖),则启用 AOP 自动代理。
  • 否则,进入 NoAspectJAutoProxyingConfiguration,不启用 AOP。

✅ 4:注册 AnnotationAwareAspectJAutoProxyCreator

@Bean
@ConditionalOnMissingBean(AnnotationAwareAspectJAutoProxyCreator.class)
public AnnotationAwareAspectJAutoProxyCreator aspectJAutoProxyCreator() {
    AnnotationAwareAspectJAutoProxyCreator proxyCreator = new AnnotationAwareAspectJAutoProxyCreator();
    proxyCreator.setProxyTargetClass(true); // 默认使用 CGLIB 代理
    return proxyCreator;
}
  • AnnotationAwareAspectJAutoProxyCreator 是 Spring AOP 的核心组件。
  • 它实现了 BeanPostProcessor 接口,在 Bean 初始化后生成代理对象。

✅ 5:AOP 自动代理的执行流程

  1. Spring 容器启动时

    • AopAutoConfiguration 注册了 AnnotationAwareAspectJAutoProxyCreator
  2. Bean 初始化完成后

    • AnnotationAwareAspectJAutoProxyCreator.postProcessAfterInitialization() 被调用。
    • 该方法会为匹配的 Bean 创建代理对象(JDK / CGLIB)。
  3. 方法调用时

    • 代理对象拦截方法调用,执行切面逻辑(@Before, @After, @Around 等)。

⚙️ 三、如何自定义 AOP 行为

✅ 1. 修改代理方式(JDK 动态代理 vs CGLIB 代理)

Spring Boot 默认使用 CGLIB 代理,可通过配置文件修改:

spring.aop.proxy-target-class=false
  • true(默认):使用 CGLIB 代理(子类继承)
  • false:使用 JDK 动态代理(接口实现)

✅ 2. 自定义切面(Aspect)

只需添加 @Aspect 注解的类即可,Spring Boot 会自动识别并织入切面逻辑:

@Aspect
@Component
public class LoggingAspect {

    @Before("execution(* com.example.service.*.*(..))")
    public void logBefore(JoinPoint joinPoint) {
        System.out.println("Before method: " + joinPoint.getSignature().getName());
    }
}

✅ 3. 自定义 Advisor 或 Advice

可以通过注册 AdvisorAdvice 来扩展 AOP 功能:

@Bean
public Advisor myAdvisor() {
    return new DefaultPointcutAdvisor(new MyPointcut(), new MyAdvice());
}

❗ 四、AOP 自动装配的常见问题与解决方案

问题 原因 解决方案
AOP 不生效 未引入 aspectjweaver 依赖 添加依赖 <dependency><groupId>org.aspectj</groupId><artifactId>aspectjweaver</artifactId></dependency>
AOP 无法拦截 private 方法 JDK 动态代理只能拦截 public 方法 使用 CGLIB 代理(默认)或改为 public 方法
AOP 无法拦截内部调用(self-invocation) 代理对象只拦截外部调用 注入自身 Bean 调用:self.method()
AOP 与事务管理器冲突 事务代理和 AOP 代理顺序冲突 使用 @Order 控制切面顺序,或使用 TransactionInterceptor

✅ 五、总结

特性 Spring Boot AOP 自动装配
启用方式 @EnableAutoConfiguration 自动启用
自动配置类 AopAutoConfiguration
默认代理方式 CGLIB(proxyTargetClass = true
自动识别切面 支持 @Aspect 注解
自定义代理方式 通过 spring.aop.proxy-target-class 配置
失效场景 未引入 aspectjweaver、方法非 public、self-invocation

🧩 六、完整流程图(简化版)

@SpringBootApplication
 └── @EnableAutoConfiguration
      └── 导入 AutoConfigurationImportSelector
           └── 加载 AopAutoConfiguration
                └── 判断是否存在 Advice.class
                     ├── 是:注册 AnnotationAwareAspectJAutoProxyCreator(AOP 自动代理)
                     └── 否:不启用 AOP
                           └── Bean 初始化时调用 postProcessAfterInitialization()
                                └── 创建代理对象(JDK / CGLIB)
                                     └── 方法调用时执行切面逻辑(@Before, @After, @Around)


网站公告

今日签到

点亮在社区的每一天
去签到