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


    如何开启AOP功能

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

    开启的原理是什么

    我们知道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的功能,本质就是向容器中注册了一个BeanDefinition。

    BeanDefinitionParser解析ao元素:

    	public BeanDefinition parse(Element element, ParserContext parserContext) {
    		// 注册启用aop功能的bean【注册AspectJAnnotationAutoProxyCreator】
    		AopNamespaceUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(parserContext, element);
    
    		// 解析子元素
    		extendBeanDefinition(element, parserContext);
    		return null;
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    注册AnnotationAwareAspectJAutoProxyCreator:

    public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(
            BeanDefinitionRegistry registry, @Nullable Object source) {
    
        return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    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);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

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

  • 相关阅读:
    数字金融面板数据:金融效率、数字金融指数、不变价GDP、经济开放度
    [每周一更]-(第73期):介绍容器监控工具-CAdvisor
    布隆过滤器的优缺点及哈希切割问题
    Vue3 - Suspense 组件介绍及使用方法
    gepc 分数计算
    Vue 2与Vue 3生命周期钩子的对比分析
    第二十一章《万年历》第1节:万年历项目简介
    [Url 链接访问图片不展示]
    二分查找算法
    MyBatis 如何使用set标签呢?
  • 原文地址:https://blog.csdn.net/yuchangyuan5237/article/details/126815996