文章目录
AOP系列文章链接地址
Spring AOP系列学习笔记一:AOP简介
Spring AOP系列学习笔记二:AOP入口分析
Spring AOP系列学习笔记三:AOP注解原理分析
Spring AOP系列学习笔记四:AOP具体调用流程分析
前言
我们分析基于注解的aop应该如何做,无论是xml配置(<aop:aspectj-autoproxy /> ),还是用纯注解(@EnableAspectJAutoProxy)的形式,首先找到她注册的入口在哪。
基于xml的方式
在Spring会从“META-INF/spring.handlers” 配置文件中拿到该注解对应的 NamespaceHandlerSupport:AopNamespaceHandler
public class AopNamespaceHandler extends NamespaceHandlerSupport {
public AopNamespaceHandler() {
}
public void init() {
this.registerBeanDefinitionParser("config", new ConfigBeanDefinitionParser());
this.registerBeanDefinitionParser("aspectj-autoproxy", new AspectJAutoProxyBeanDefinitionParser());
this.registerBeanDefinitionDecorator("scoped-proxy", new ScopedProxyBeanDefinitionDecorator());
this.registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser());
}
}
在这儿会有注册四个,aspectj-autoproxy对应的bean是AspectJAutoProxyBeanDefinitionParser,进入AspectJAutoProxyBeanDefinitionParser#parse方法。
AspectJAutoProxyBeanDefinitionParser#parse
@Override
@Nullable
public BeanDefinition parse(Element element, ParserContext parserContext) {
1、注册AspectJAnnotationAutoProxyCreator
AopNamespaceUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(parserContext, element);
extendBeanDefinition(element, parserContext);
return null;
}
1、注册AspectJAnnotationAutoProxyCreator 见代码块一
代码块一:registerAspectJAnnotationAutoProxyCreatorIfNecessary
public static void registerAspectJAnnotationAutoProxyCreatorIfNecessary(
ParserContext parserContext, Element sourceElement) {
1、注册AspectJAnnotationAutoProxyCreator
BeanDefinition beanDefinition = AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(
parserContext.getRegistry(), parserContext.extractSource(sourceElement));
2、对于proxy-target-class以及expose-proxy属性的处理
useClassProxyingIfNecessary(parserContext.getRegistry(), sourceElement);
3、注册组件并通知,便于监听器做进一步处理
registerComponentIfNecessary(beanDefinition, parserContext);
}
代码块二:AopConfigUtils#registerAspectJAnnotationAutoProxyCreatorIfNecessary
@Nullable
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry,
@Nullable Object source) {
1、终于见到本尊AnnotationAwareAspectJAutoProxyCreator
return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
}
@Nullable
private static BeanDefinition registerOrEscalateApcAsRequired(Class<?> cls, BeanDefinitionRegistry registry,
@Nullable Object source) {
Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
1、先从缓存中判断是否已经注册过了,可能存在的bean有一下三种
InfrastructureAdvisorAutoProxyCreator、AspectJAwareAdvisorAutoProxyCreator、AnnotationAwareAspectJAutoProxyCreator
if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
2、直接从缓存中获取bean
BeanDefinition apcDefinition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
3、如果已经注册过的bean和我们当前的bean不相同,则按照优先级来选择需要哪个bean
if (!cls.getName().equals(apcDefinition.getBeanClassName())) {
4、获取缓存中的bean的优先级
int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName());
5、获取入参bean的优先级
int requiredPriority = findPriorityForClass(cls);
if (currentPriority < requiredPriority) {
6、如果要注册的优先级较高则注册
apcDefinition.setBeanClassName(cls.getName());
}
}
7、如果bean相同,不做操作
return null;
}
8、如果注册表中还不存在,则新建一个Bean定义,并添加到注册表中
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;
}
org.springframework.aop.config.internalAutoProxyCreator 是内部管理的自动代理创建者的 bean 名称,可能对应的 beanClassName 有三种,对应的注解如下:
InfrastructureAdvisorAutoProxyCreator:<tx:annotation-driven />
AspectJAwareAdvisorAutoProxyCreator:<aop:config />
AnnotationAwareAspectJAutoProxyCreator:<aop:aspectj-autoproxy />
当同时存在多个注解时,会使用优先级最高的 beanClassName 来作为 org.springframework.aop.config.internalAutoProxyCreator 的 beanClassName。本系列文章暂不考虑同时存在其他注解的情况,所以在这边会注册的 beanClassName 为:AnnotationAwareAspectJAutoProxyCreator。
代码块三:useClassProxyingIfNecessary
private static void useClassProxyingIfNecessary(BeanDefinitionRegistry registry, @Nullable Element sourceElement) {
if (sourceElement != null) {
boolean proxyTargetClass = Boolean.valueOf(sourceElement.getAttribute(PROXY_TARGET_CLASS_ATTRIBUTE));
if (proxyTargetClass) {
AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
}
boolean exposeProxy = Boolean.valueOf(sourceElement.getAttribute(EXPOSE_PROXY_ATTRIBUTE));
if (exposeProxy) {
AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
}
}
}
基于注解@EnableAspectJAutoProxy的方式
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(AspectJAutoProxyRegistrar.class)
public @interface EnableAspectJAutoProxy {
/**
* Indicate whether subclass-based (CGLIB) proxies are to be created as opposed
* to standard Java interface-based proxies. The default is {@code false}.
*/
boolean proxyTargetClass() default false;
/**
* Indicate that the proxy should be exposed by the AOP framework as a {@code ThreadLocal}
* for retrieval via the {@link org.springframework.aop.framework.AopContext} class.
* Off by default, i.e. no guarantees that {@code AopContext} access will work.
* @since 4.3.1
*/
boolean exposeProxy() default false;
}
可以看到该注解引入了AspectJAutoProxyRegistrar类,进入该类查看。
代码块四:AspectJAutoProxyRegistrar
class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {
@Override
public void registerBeanDefinitions(
AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
1、注册AspectJAnnotationAutoProxyCreatorIfNecessary
AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
2、注册EnableAspectJAutoProxy注解
AnnotationAttributes enableAspectJAutoProxy =
AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);
3、解析proxyTargetClass和exposeProxy属性
if (enableAspectJAutoProxy != null) {
if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {
AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
}
if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {
AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
}
}
}
}
1、注册AspectJAnnotationAutoProxyCreatorIfNecessary就进入了代码块二,无论基于注解和xml的形式其实大同小异,一个懂了另一个也就不学自通了。