前言
AOP是spring的重点和难点,它的本质是用动态代理增强容器中bean的方法,本篇从基于注解的AOP开发方式开始分析。当你需要进行AOP切面编程时,首相要引入一个注解:@EnableAspectJAutoProxy。
@EnableAspectJAutoProxy
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(AspectJAutoProxyRegistrar.class)
public @interface EnableAspectJAutoProxy {
//是否使用cglib动态代理,默认时false
boolean proxyTargetClass() default false;
//是否暴露代理到本地线程变量,默认false
boolean exposeProxy() default false;
}
可以看到在@Import中引入了AspectJAutoProxyRegistrar,这是一个ImportBeanDefinitionRegistrar,可以向spring容器注册一个BeanDefinition:
class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {
@Override
public void registerBeanDefinitions(
AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
//注册aop相关的bean
AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
AnnotationAttributes enableAspectJAutoProxy =
AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);
if (enableAspectJAutoProxy != null) {
if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {
AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
}
if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {
AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
}
}
}
}
一路来到注册的代码:
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(
BeanDefinitionRegistry registry, @Nullable Object source) {
return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
}
private static BeanDefinition registerOrEscalateApcAsRequired(
Class<?> cls, BeanDefinitionRegistry registry, @Nullable Object source) {
//如果容器中已经有了名为AUTO_PROXY_CREATOR_BEAN_NAME的bean,则会根据优先级Priority选择是否覆盖
//如果同时开启了aop和声明式事务会有两个bean,aop会覆盖声明式事务
if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
BeanDefinition apcDefinition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
if (!cls.getName().equals(apcDefinition.getBeanClassName())) {
int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName());
int requiredPriority = findPriorityForClass(cls);
if (currentPriority < requiredPriority) {
apcDefinition.setBeanClassName(cls.getName());
}
}
return null;
}
RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
beanDefinition.setSource(source);
//设置最高优先级
beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE);
beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
//注册BeanDefinition
registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);
return beanDefinition;
}
最终注册到容器中的bean为:AnnotationAwareAspectJAutoProxyCreator,这个bean会在spring容器加载时解析aspect切面,把切面中的方法解析为一个个通知器Advisor,并在bean的初始化后置调用中为bean创建代理对象。
总结
@EnableAspectJAutoProxy这个注解是spirng AOP的入口,下篇将会详细分析解析切面的流程。