Spring之【初识AOP】

目录

先简单使用下AOP功能体验一下效果

自定义注解

定义一个切面类

业务类

开启AOP功能

测试一下效果

@EnableAspectJAutoProxy注解

思考!

将@EnableAspectJAutoProxy注解去掉

自定义实现BeanDefinitionRegistryPostProcessor

测试效果

AnnotationAwareAspectJAutoProxyCreator


先简单使用下AOP功能体验一下效果

自定义注解

java 复制代码
package spring.aop;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * 该注解只能用在方法上
 */
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Log {
}

定义一个切面类

java 复制代码
package spring.aop;

import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

/**
 * 切面
 */
@Aspect
@Component
public class LogAspect {

    /**
     * 切入点表达式
     * 增强有@Log注解的方法
     */
    @Pointcut("@annotation(spring.aop.Log)")
    public void pointCut() {

    }

    /**
     * 定义前置增强逻辑
     */
    @Before("pointCut()")
    public void before() {
        System.out.println("Log...before...");
    }

    /**
     * 定义后置增强逻辑
     */
    @After("pointCut()")
    public void after() {
        System.out.println("Log...after...");
    }
}

业务类

java 复制代码
package spring.aop;

import org.springframework.stereotype.Service;

@Service
public class AccountService {
    /**
     * 需要被增强的方法
     */
    @Log
    public void register() {
        System.out.println("AccountService#register...");
    }
}

开启AOP功能

java 复制代码
package spring.aop;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.EnableAspectJAutoProxy;

/**
 * 开启AOP功能
 */
@EnableAspectJAutoProxy
@ComponentScan("spring.aop")
public class SpringConfig {
}

测试一下效果

java 复制代码
package spring.aop;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class AopMain {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(SpringConfig.class);
        AccountService accountService = applicationContext.getBean(AccountService.class);
        accountService.register();
    }
}

@EnableAspectJAutoProxy注解

  • Spring容器启动
  • 容器启动过程中会执行BeanDefinitionRegistryPostProcessor的方法回调【invokeBeanFactoryPostProcessor(beanFactory)】
  • ConfigurationClassPostProcessor是BeanDefinitionRegistryPostProcessor的实现类,因此会执行ConfigurationClassPostProcessor的postProcessBeanDefinitionRegistry方法
  • ConfigurationClassPostProcessor的postProcessBeanDefinitionRegistry方法逻辑中会解析到组件类上的**@EnableAspectJAutoProxy注解上的@Import(AspectJAutoProxyRegistrar.class)**【processImports方法】
  • AspectJAutoProxyRegistrar实现了ImportBeanDefinitionRegistrar接口,通过ParserStrategyUtils的instantiateClass方法将其实例化并放入importBeanDefinitionRegistrars集合中
  • 最后通过loadBeanDefinitionsFromRegistrars方法对importBeanDefinitionRegistrars集合进行遍历,分别调用它们的registerBeanDefinitions方法
  • AspectJAutoProxyRegistrar的registerBeanDefinitions方法中的主要逻辑是将AnnotationAwareAspectJAutoProxyCreator对应的RootBeanDefinition放入容器的beanDefinitionMaps集合中

思考!

通过上面的介绍可知,将AnnotationAwareAspectJAutoProxyCreator对应的BeanDefinition对象放入容器中,后续的AOP功能就会生效

疑问:那如果我不使用@EnableAspectJAutoProxy,而是随便采用一种方式将AnnotationAwareAspectJAutoProxyCreator的BeanDefinition对象放入容器中,如自定义BeanDefinitionRegistryPostProcessor来做到这一点的话,AOP功能是不是同样会生效?现在就来验证一下

将@EnableAspectJAutoProxy注解去掉

java 复制代码
package spring.aop;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.EnableAspectJAutoProxy;

/**
 * 这里注释掉开启AOP功能的注解
 */
//@EnableAspectJAutoProxy
@ComponentScan("spring.aop")
public class SpringConfig {
}

自定义实现BeanDefinitionRegistryPostProcessor

java 复制代码
package spring.aop;

import org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.stereotype.Component;

/**
 * 自定义BeanDefinitionRegistryPostProcessor实现其postProcessBeanDefinitionRegistry方法
 */
@Component
public class CustomBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {
    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
        // 将AnnotationAwareAspectJAutoProxyCreator的BeanDefinition对象放入容器中
        RootBeanDefinition rootBeanDefinition = new RootBeanDefinition();
        rootBeanDefinition.setBeanClass(AnnotationAwareAspectJAutoProxyCreator.class);
        registry.registerBeanDefinition("aop", rootBeanDefinition);
    }

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {

    }
}

测试效果

AOP功能生效

AnnotationAwareAspectJAutoProxyCreator

看一下AnnotationAwareAspectJAutoProxyCreator的继承体系图,即它是一个Bean后置处理器

相关推荐
腻害兔3 小时前
【若依项目-产品经理视角】深度拆解 RuoYi-Vue-Pro 商城模块:从商品管理到交易引擎,50 张表撑起一整套电商系统
java·大数据·vue.js·产品经理·ai编程
码智社4 小时前
AES加密原理详解及Java实现加解密实战
java·开发语言
萧瑟余晖5 小时前
JDK 26 新特性详解
java·开发语言
马优晨6 小时前
Freemarker 完整讲解(后端 Java 模板引擎)
java·开发语言·freemarker·freemarker 完整讲解·freemarker模板引擎
维天说8 小时前
CLI-Switch 2026年3月版历史设计:Hook、TTY 隔离与 JSON 状态
java·服务器·json
Zane19949 小时前
并发 vs 并行:别再傻傻分不清了,一文讲透 Java 并发编程的第一课
java·后端
噢,我明白了10 小时前
java中Excel的导入和导出(EasyExcel)
java·开发语言·excel
吠品10 小时前
Zabbix Web界面误报Server未运行的排查与解决
java·服务器·数据库
啊湘10 小时前
天气查询API接口 按月Token鉴权 实时天气 物联网可用 文档齐全
java·后端·struts
Java内核笔记11 小时前
告别十亿美元的错误 : Spring Boot 4 空安全 (JSpecify) 实战
java·spring boot·后端