Spring AOP
当前分析的Spring 版本 5.0
Spring 2.0开始采用@AspectJ注解对POJO标注,使用切点表达式语法进行切点定义.
Spring支持注解的AOP,需要在配置文件xml中配置<aop:aspectj-autoproxy />
在Spring中自定义的注解和自定义的标签都会在Spring中找到 注册该注解或者标签的对应解析器。
一、注册解析器-init()追溯
在配置文件中配置了 <aop:aspectj-autoproxy /> ,在AopNamespaceHandler类中注册了aspectj-autoproxy,
public class AopNamespaceHandler extends NamespaceHandlerSupport {
/**
* Register the {@link BeanDefinitionParser BeanDefinitionParsers} for the
* '{@code config}', '{@code spring-configured}', '{@code aspectj-autoproxy}'
* and '{@code scoped-proxy}' tags.
*/
@Override
public void init() {
// In 2.0 XSD as well as in 2.1 XSD.
registerBeanDefinitionParser("config", new ConfigBeanDefinitionParser());
registerBeanDefinitionParser("aspectj-autoproxy", new AspectJAutoProxyBeanDefinitionParser());
registerBeanDefinitionDecorator("scoped-proxy", new ScopedProxyBeanDefinitionDecorator());
// Only in 2.0 XSD: moved to context namespace as of 2.1
registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser());
}
}
AopNamespaceHandler类init()方法
1、这里是 解析自定义元素节点 调用parseCustomElement(Element ele, @Nullable BeanDefinition containingBd)方法
从上图可知,追溯调用了
-->XmlBeanDefinitionReader类的 loadBeanDefinitions(Resource resource) 方法
@Override
public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException {
return loadBeanDefinitions(new EncodedResource(resource));
}
由上图可知,一步一步从refresh()方法,一步一步 调用了到XmlBeanDefinitionReader类的 loadBeanDefinitions(Resource resource) 方法 最后开始在AopNamespaceHandler类中注册了aspectj-autoproxy,
2、这里是对子标签下的自定义属性调用decorateBeanDefinitionIfRequired方法进行解析 追溯到开始也调用了 loadBeanDefinitions方法 也就是开始解析xml文件的时候开始
二、注册解析器
所有的解析器,都实现了BeanDefinitionParser接口,入口都是从BeanDefinitionParser接口的方法parse()开始
AspectJAutoProxyBeanDefinitionParser类的parse方法如下:
@Override
@Nullable
public BeanDefinition parse(Element element, ParserContext parserContext) {
AopNamespaceUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(parserContext, element);//注册AnnotationAwareAspectJAutoProxyCreator
extendBeanDefinition(element, parserContext);//对于注解中子类的处理
return null;
}
AspectJAutoProxyBeanDefinitionParser类的parse方法追溯如下,也是从loadBeanDefinitions()
-->loadBeanDefinitions(EncodedResource)
-->doLoadBeanDefinitions()
-->registerBeanDefinitions()
-->一步一步 最后到--》parse()方法
parse方法里面的registerAspectJAnnotationAutoProxyCreatorIfNecessary方法实现如下:
public static void registerAspectJAnnotationAutoProxyCreatorIfNecessary(
ParserContext parserContext, Element sourceElement) {
//注册或升级AutoProxyCreator定义beanName为org.Springframework.aop.config.internalAutoProxyCreator的BeanDefinition
BeanDefinition beanDefinition = AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(
parserContext.getRegistry(), parserContext.extractSource(sourceElement));
useClassProxyingIfNecessary(parserContext.getRegistry(), sourceElement); //对于proxy-target-class以及expose-proxy属性的处理
registerComponentIfNecessary(beanDefinition, parserContext);//注册组件并通知,便于监听器做进一步处理,其中beanDefinition的className是AnnotationAwareAspectJAutoProxyCreator
}
1、-->AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary
-->AopConfigUtils类的
@Nullable
private static BeanDefinition registerOrEscalateApcAsRequired(Class<?> cls, BeanDefinitionRegistry registry,
@Nullable 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) {
apcDefinition.setBeanClassName(cls.getName()); //这里拿到已经创建的创建器,然后设置beanClassName
}
}
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;
}
2、--> AopNamespaceUtils类的registerAspectJAnnotationAutoProxyCreatorIfNecessary方法的
-》useClassProxyingIfNecessary(parserContext.getRegistry(), sourceElement);
useClassProxyingIfNecessary实现了 proxy-target-class属性和expose-proxy属性的处理
private static void useClassProxyingIfNecessary(BeanDefinitionRegistry registry, @Nullable Element sourceElement) {
if (sourceElement != null) {//处理proxy-target-class属性
boolean proxyTargetClass = Boolean.parseBoolean(sourceElement.getAttribute(PROXY_TARGET_CLASS_ATTRIBUTE));
if (proxyTargetClass) {
AopConfigUtils.forceAutoProxyCreat