说明:本系列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引入的,首先查看该类
确实引入了AspectJAutoProxyRegistrar,注意到CglibAutoProxyConfiguration是AopAutoConfiguration的内部类。
在这边发现了@ConditionalOnClass注解,原来,只有括号中的类在项目存在的时候,才会解析,而这个Advice类正好是aspectj包下的,连AopAutoConfiguration都不会解析,更别说它的内部类了,自然也不存在importBeanDefinitionRegistrars这样的属性。
这也就解释了引入aspectj包后比没引入多返回一个bean的原因了。