我们知道,Spring默认不支持@AspectJ风格的切面声明,为了支持需要使用如下配置:<aop:aspectj-autoproxy/>
,或者使用@EnableAspectJAutoProxy
注解。现在流行使用注解,那我们就以@EnableAspectJAutoProxy
这个注解为源头来学习Spring AOP的源码。
从@EnableAspectJAutoProxy开始看起
先来看一下注解的源码:
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(AspectJAutoProxyRegistrar.class)
public @interface EnableAspectJAutoProxy {
/**
* true——使用CGLIB基于类创建代理;false——使用JDK动态代理基于接口创建代理
*/
boolean proxyTargetClass() default false;
/**
* 是否通过aop框架暴露该代理对象
*/
boolean exposeProxy() default false;
}
我们发现它import了一个AspectJAutoProxyRegistrar,进一步查看其源码:
class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {
/**
* Register, escalate, and configure the AspectJ auto proxy creator based on the value
* of the @{@link EnableAspectJAutoProxy#proxyTargetClass()} attribute on the importing
* {@code @Configuration} class.
*/
@Override
public void registerBeanDefinitions(
AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
//注册AnnotationAwareAspectJAutoProxyCreator
AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
AnnotationAttributes enableAspectJAutoProxy =
AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);
//对于proxyTargetClass以及exposeProxy属性为true的处理
if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {
AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
}
if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {
AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
}
}
}
看AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
这行代码的详细实现
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry) {
return registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry, null);
}
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry, Object source) {
// 这里容器中注册了一个AnnotationAwareAspectJAutoProxyCreator的bean。
return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
}
代码看到这里,可以知道AnnotationAwareAspectJAutoProxyCreator是个非常重要的class。
注册AnnotationAwareAspectJAutoProxyCreator
接着上面的代码,继续看,就是AnnotationAwareAspectJAutoProxyCreator的注册或升级过程。
private static BeanDefinition registerOrEscalateApcAsRequired(Class<?> cls, BeanDefinitionRegistry registry, Object source) {
Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
如果已经存在了自动代理创建器,且存在的自动代理创建器与现在的不一致,那么需要根据优先级来判断到底需要使用哪个
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) {
//改变bean最重要的就是改变bean所对应的className属性
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);
registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);
return beanDefinition;
}
处理proxyTargetClass和exposeProxy
@EnableAspectJAutoProxy注解的源码中有两个方法:
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(AspectJAutoProxyRegistrar.class)
public @interface EnableAspectJAutoProxy {
/**
* true——使用CGLIB基于类创建代理;false——使用JDK动态代理基于接口创建代理
*/
boolean proxyTargetClass() default false;
/**
* 是否通过aop框架暴露该代理对象
*/
boolean exposeProxy() default false;
}
在对这两个属性做了处理,如果proxyTargetClass属性为true,则强制使用CGLIB代理。如果exposeProxy为true,则暴露当前代理对象为ThreadLocal模式。
if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {
AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
}
if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {
AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
}
强制使用的过程,也是设置BeanDefinition属性的过程
public static void forceAutoProxyCreatorToUseClassProxying(BeanDefinitionRegistry registry) {
if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
BeanDefinition definition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
definition.getPropertyValues().add("proxyTargetClass", Boolean.TRUE);
}
}
public static void forceAutoProxyCreatorToExposeProxy(BeanDefinitionRegistry registry) {
if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
BeanDefinition definition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
definition.getPropertyValues().add("exposeProxy", Boolean.TRUE);
}
}
以上就是AnnotationAwareAspectJAutoProxyCreator的注册过程。注册完后,是做了什么工作来实现AOP的操作呢?且听下回分解。