• AOP原理分析《三》- AOP总体流程


    总体流程图

    介绍后置处理器

    开启aop后的BeanDefinition的注册在上文已经说明了。

    在注册阶段只是向容器中注册了一个BeanDefinition的定义,而这个BeanDefinition又不是一个简单的BeanDefinition而是实现了一些特殊的接口,
    不妨先了解下这个注册的BeanDefinition的结构。

    AnnotationAwareAspectJAutoProxyCreator的结构

    分析了该bean的体系结构,如下图:

    可以看出实现了SmartInstantiationAwareBeanPostProcessor、InstantiationAwareBeanPostProcessor、BeanPostProcessor等重要的拓展接口,
    那么可以猜测aop功能大致是通过在每个bean初始化前后运行"bean后置处理器"来完成aop的。

    分别介绍一下这几个接口
    (如果方法找不到请下载spring源码全局搜索一下或者找慢点)

    接口起作用的代码位置
    SmartInstantiationAwareBeanPostProcessoraddSingletonFactory方法在第三级缓存这里
    InstantiationAwareBeanPostProcessorresolveBeforeInstantiation方法 或 populateBean方法getBean的实例化前后 或 属性填充
    BeanPostProcessorinvokeInitMethods方法前后在bean初始化前后

    找到合适的增强器并创建代理

    AnnotationAwareAspectJAutoProxyCreator实现了几个特殊的接口,但是观察了对应的实现代码也就只有BeanPostProcessor
    postProcessAfterInitialization跟目标接近,而我们对AOP逻辑的分析也从这里开始。

    查找增强器并创建代理:

    protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
        if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
            return bean;
        }
    
        // 1、如果不需要代理,则直接返回原始bean就好了
        if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
            return bean;
        }
    
        // 2、advisedBeans 记录不需要代理的bean
        if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
            this.advisedBeans.put(cacheKey, Boolean.FALSE);
            return bean;
        }
    
        // Create proxy if we have advice.
        // 3、获取AdvicesAndAdvisors增强,并创建代理    
        Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
        if (specificInterceptors != DO_NOT_PROXY) {
            this.advisedBeans.put(cacheKey, Boolean.TRUE);
    		// 根据增强器创建代理对象
            Object proxy = createProxy(
                    bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
            // proxyTypes 缓存了代理结果
    		this.proxyTypes.put(cacheKey, proxy.getClass());
            return proxy;
        }
    
        this.advisedBeans.put(cacheKey, Boolean.FALSE);
        return bean;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    后文继续分析如何获取增强器

    传送门:保姆式Spring5源码解析

    欢迎与作者一起交流技术和工作生活

    联系作者

  • 相关阅读:
    Docker 使用原理流程
    【高等数学】矩阵与向量组的秩和等价
    入门小白拥有服务器的建议
    Spring工具类--AnnotatedElementUtils的使用
    工作流-普通节点转会签节点
    java计算机毕业设计高校教师科研文献管理系统MyBatis+系统+LW文档+源码+调试部署
    Java学习笔记(十七)
    File类和IO流
    如何消除误差?室内定位中的关键技术
    Hive (六) --------- 查询
  • 原文地址:https://blog.csdn.net/yuchangyuan5237/article/details/126815906