死磕Spring之AOP篇 - Spring AOP注解驱动与XML配置 (4)

这个标签的作用和 @EnableAspectJAutoProxy 注解相同,开启整个 Spring AOP 模块,原理也相同,注册一个 AnnotationAwareAspectJAutoProxyCreator 自动代理对象

AspectJAutoProxyBeanDefinitionParser

org.springframework.aop.config.AspectJAutoProxyBeanDefinitionParser,<aop:aspectj-autoproxy /> 标签对应 BeanDefinitionParse 解析器

class AspectJAutoProxyBeanDefinitionParser implements BeanDefinitionParser { @Override @Nullable public BeanDefinition parse(Element element, ParserContext parserContext) { // 解析 <aop:aspectj-autoproxy /> 标签 // 注册 AnnotationAwareAspectJAutoProxyCreator 自动代理对象(如果没有注册的话),设置为优先级最高 // 过程和 @EnableAspectJAutoProxy AopNamespaceUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(parserContext, element); // 解析 <aop:include /> 子标签,用于指定需要开启代理的路径 extendBeanDefinition(element, parserContext); return null; } private void extendBeanDefinition(Element element, ParserContext parserContext) { BeanDefinition beanDef = parserContext.getRegistry().getBeanDefinition(AopConfigUtils.AUTO_PROXY_CREATOR_BEAN_NAME); if (element.hasChildNodes()) { addIncludePatterns(element, parserContext, beanDef); } } private void addIncludePatterns(Element element, ParserContext parserContext, BeanDefinition beanDef) { ManagedList<TypedStringValue> includePatterns = new ManagedList<>(); NodeList childNodes = element.getChildNodes(); for (int i = 0; i < childNodes.getLength(); i++) { Node node = childNodes.item(i); if (node instanceof Element) { Element includeElement = (Element) node; TypedStringValue valueHolder = new TypedStringValue(includeElement.getAttribute("name")); valueHolder.setSource(parserContext.extractSource(includeElement)); includePatterns.add(valueHolder); } } if (!includePatterns.isEmpty()) { includePatterns.setSource(parserContext.extractSource(element)); beanDef.getPropertyValues().add("includePatterns", includePatterns); } } }

<aop:aspectj-autoproxy /> 标签的解析过程先通过 AopNamespaceUtils 工具类注册一个 AnnotationAwareAspectJAutoProxyCreator 自动代理对象,然后继续解析 <aop:include /> 子标签,用于指定需要开启代理的路径

AopNamespaceUtils

org.springframework.aop.config.AopNamespaceUtils,Spring AOP XML 配置文件解析工具类

public abstract class AopNamespaceUtils { public static final String PROXY_TARGET_CLASS_ATTRIBUTE = "proxy-target-class"; private static final String EXPOSE_PROXY_ATTRIBUTE = "expose-proxy"; public static void registerAspectJAnnotationAutoProxyCreatorIfNecessary( ParserContext parserContext, Element sourceElement) { // <1> 注册 AnnotationAwareAspectJAutoProxyCreator 自动代理对象(如果没有注册的话),设置为优先级最高 BeanDefinition beanDefinition = AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary( parserContext.getRegistry(), parserContext.extractSource(sourceElement)); // <2> 则根据 <aop:aspectj-autoproxy /> 标签的配置设置 AnnotationAwareAspectJAutoProxyCreator 的属性 useClassProxyingIfNecessary(parserContext.getRegistry(), sourceElement); // <3> 将注册的 BeanDefinition 也放入 `parserContext` 上下文中 registerComponentIfNecessary(beanDefinition, parserContext); } private static void useClassProxyingIfNecessary(BeanDefinitionRegistry registry, @Nullable Element sourceElement) { // 如果 <aop:aspectj-autoproxy /> 标签不为空 if (sourceElement != null) { boolean proxyTargetClass = Boolean.parseBoolean(sourceElement.getAttribute(PROXY_TARGET_CLASS_ATTRIBUTE)); if (proxyTargetClass) { // 设置 `proxyTargetClass` 为 `true`(开启类代理,也就是开启 CGLIB 动态代理) AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry); } boolean exposeProxy = Boolean.parseBoolean(sourceElement.getAttribute(EXPOSE_PROXY_ATTRIBUTE)); if (exposeProxy) { // 设置 `exposeProxy` 为 `true`(需要暴露代理对象,也就是在 Advice 或者被拦截的方法中可以通过 AopContext 获取代理对象) AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry); } } } private static void registerComponentIfNecessary(@Nullable BeanDefinition beanDefinition, ParserContext parserContext) { if (beanDefinition != null) { parserContext.registerComponent( new BeanComponentDefinition(beanDefinition, AopConfigUtils.AUTO_PROXY_CREATOR_BEAN_NAME)); } } }

注册 AnnotationAwareAspectJAutoProxyCreator 自动代理对象的过程和 @EnableAspectJAutoProxy 注解类型,这里不再做讲述

<aop:scoped-proxy /> <beans> <bean > <aop:scoped-proxy /> </bean> </beans>

<aop:scoped-proxy /> 标签需要定义在 <bean /> 中,用来装饰这个 Bean,会生成一个 ScopedProxyFactoryBean 类型的 RootBeanDefinition 对象并注册。ScopedProxyFactoryBean 是一个 FactoryBean,在其 getObject() 方法中返回的是一个代理对象。也就是说 <aop:scoped-proxy /> 标签可以将一个 Bean 进行 AOP 代理。

ScopedProxyBeanDefinitionDecorator

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zygssw.html