AOP 原理分析《二》- 如何开启 AOP 功能

如何开启AOP功能

  • 通过注解方式
@Configuration
@EnableAspectJAutoProxy
public class AppConfig {
    
}
  • 通过xml配置方式
<aop:aspectj-autoproxy/>

开启的原理是什么

我们知道Spring提供了众多的拓展接口,BeanPOstProcessor是在bean初始化前后起作用的
重要拓展接口,而aop功能是通过代理实现的,那么很有可能就是通过BeanPostProcessor后置处理器实现的。
这里以xml开启aop为例开始分析:

解析aop:aspectj-autoproxy/元素

在spring的xml解析文章中分析了spring解析xml文件的流程,简单回顾一下:
1、根据元素的namespace找到handler(如spring.handlers文件中的AopNamespaceHandler)
2、根据元素的名称找到对应的解析器(如aop:aspectj-autoproxy/的解析器是AspectJAutoProxyBeanDefinitionParser)
3、spring会回调解析器的parse方法得到BeanDefinition对象

注册AnnotationAwareAspectJAutoProxyCreator

1、
当通过@EnableAspectJAutoProxy<aop:aspectj-autoproxy>方式开启aop的功能,本质就是向容器中注册了一个BeanDefinition。

BeanDefinitionParser解析ao元素:

	public BeanDefinition parse(Element element, ParserContext parserContext) {
		// 注册启用aop功能的bean【注册AspectJAnnotationAutoProxyCreator】
		AopNamespaceUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(parserContext, element);

		// 解析子元素
		extendBeanDefinition(element, parserContext);
		return null;
	}

注册AnnotationAwareAspectJAutoProxyCreator:

public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(
        BeanDefinitionRegistry registry, @Nullable Object source) {

    return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
}

2、给BeanDefinition添加属性
把xml解析到的子元素添加到BeanDefinition的includePatterns属性中。

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));
        // 【最后吧子元素加入到BeanDefinition中的属性中】
        // 既然加入的是属性,那么你知道他会在"属性填充"阶段吧值填充到bean instance中把
        beanDef.getPropertyValues().add("includePatterns", includePatterns);
    }
}

欢迎微信搜索公众号“火鱼Java杂谈”,保姆式Spring5源码教程与你仅差一个关注。
火鱼Java杂谈
保姆式Spring5源码注释一角

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Fire Fish

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值