SpringBoot AoP(1)环境准备

343 阅读1分钟

说明:本系列AoP部分结合spring boot情境,spring boot的版本为2.1.1.RELEASE,aop相关版本为5.1.3.RELEASE。

准备代码

jar包

    <dependency>
        <groupId>org.aspectj</groupId>
        <artifactId>aspectjweaver</artifactId>
        <version>1.9.2</version>
    </dependency>

aop切面

@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface HodayDouble {
}

@Aspect
@Component
public class OperationAop {
    @Pointcut("@annotation(com.hx.anno.HodayDouble)")
    public void doCut(){}

    @Around("doCut()")
    public int doAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        Object[] args = proceedingJoinPoint.getArgs();
        int i = (int) args[0];
        int j = (int) args[1];
        System.out.println("入参:i:" + i);
        System.out.println("入参:j:" + j);
        System.out.println("before around");
        int result = (int) proceedingJoinPoint.proceed();
        System.out.println("after around");
        System.out.println("原始结果:" + result);

        result = result * 2;
        System.out.println("代理结果:" + result);
        return result;
    }

    @Before("doCut()")
    public void doBefore(){
        System.out.println("@Before print");
    }

    @After("doCut()")
    public void doAfter(){
        System.out.println("@After print");
    }

    public void test(){

    }
}

代理类

@Component
public class OperationUtil {

    @HodayDouble
    public int add(int i, int j){
        int result = i + j;
        return result;
    }
}

普通类

@Service("service")
public class OperationService {

    @Autowired
    private OperationUtil ops;

    public int add(int i , int j){
        return ops.add(i,j);
    }
}

后置处理器分析

AbstractApplicationContext->refresh():
    // 注册后置处理器
    registerBeanPostProcessors(beanFactory);
AbstractApplicationContext->registerBeanPostProcessors():
    PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this);
PostProcessorRegistrationDelegate->registerBeanPostProcessors():
    String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);

上面代码将会从IoC容器的beanDefinitionNames遍历,找到实现了BeanPostProcessor接口的bean,以String数组的形式返回,发现在引入了aspectj包之后,多出来一个org.springframework.aop.config.internalAutoProxyCreator,这引发了我的思考

执行beanDefinitionMap.get("org.springframework.aop.config.internalAutoProxyCreator"),返回的是AnnotationAwareAspectJAutoProxyCreator类,将该类添加到beanPostProcessors变量中,这是实现AoP的一个后置处理器

从何而来

往上回溯,发现在添加配置类bean的时候,有一个名为org.springframework.boot.autoconfigure.aop.AopAutoConfiguration$CglibAutoProxyConfiguration的bean,加载过程如下:

ConfigurationClassBeanDefinitionReader->loadBeanDefinitionsForConfigurationClass():
    loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars());
ConfigurationClassBeanDefinitionReader->loadBeanDefinitionsFromRegistrars:
    registrars.forEach((registrar, metadata) ->
            registrar.registerBeanDefinitions(metadata, this.registry));
AspectJAutoProxyRegistrar->registerBeanDefinitions():
    AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
AopConfigUtils->registerAspectJAnnotationAutoProxyCreatorIfNecessary():
    return registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry, null);
AopConfigUtils->registerAspectJAnnotationAutoProxyCreatorIfNecessary():
    return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);

原来是通过importBeanDefinitionRegistrars属性,在这里添加到bdMap和bdNames中的

为何会有

既然是org.springframework.boot.autoconfigure.aop.AopAutoConfiguration$CglibAutoProxyConfiguration引入的,首先查看该类

image.png

image.png

确实引入了AspectJAutoProxyRegistrar,注意到CglibAutoProxyConfigurationAopAutoConfiguration的内部类。

image.png

在这边发现了@ConditionalOnClass注解,原来,只有括号中的类在项目存在的时候,才会解析,而这个Advice类正好是aspectj包下的,连AopAutoConfiguration都不会解析,更别说它的内部类了,自然也不存在importBeanDefinitionRegistrars这样的属性。

这也就解释了引入aspectj包后比没引入多返回一个bean的原因了。