• 【04】Spring源码-手写篇-手写AOP实现(下)


    在这里插入图片描述

    接上一篇文章继续

    四、织入实现

    1. 织入的分析

      织入要完成的是什么?织入其实就是要把用户提供的增强功能加到指定的方法上。

    image.png

    思考1:在什么时候织入?

      创建Bean实例的时候,在Bean初始化后,再对其进行增强。

    思考2:如何确定bean要增强?

      对bean类及方法挨个匹配用户配置的切面,如果有切面匹配就是要增强

    思考3:如何实现织入?

      代理方式

    2.织入的设计

      为了更好的去设计织入的实现,先整理下AOP的使用流程。

    image.png

    这里我们要考虑匹配、织入逻辑写到哪里?是写在BeanFactory中吗?

    这时我们要考虑如果我们直接在BeanFactory中来处理,后续如果还有其他的需求是不是也要在BeanFactory中处理呢?这样操作有什么不好的地方呢?

    • BeanFactory代码爆炸,不专情
    • 不易扩展

    那我们应该要怎么来设计呢?

    我们先来回顾下Bean的生产的过程

    image.png

    在这个过程中, 将来会有更多处理逻辑加入到Bean生产过程的不同阶段。我们现在最好是设计出能让我们后面不用再改BeanFactory的代码就能灵活的扩展。

    这时我们可以考虑用观察者模式,通过在各个节点加入扩展点,加入注册机制。

    image.png

    那么在这块我们就应用观察者模式来加入一个Bean的后置处理器 BeanPostProcessor

    image.png

    具体的我们在代码中来看看。

    3.织入的实现

    3.1 分析

      我们先定义了 BeanPostProcessor 接口,在这个接口中我们定义了相关的行为,也就是初始化之前和初始化之后要执行的方法。

    image.png

      那么在此处我们需要在BeanFactory对创建的Bean对象做初始化前后要校验是否需要做相关的增强操作。

    image.png

      在BeanFactory中我们提供了BeanPostProcessor的注册方法。

    image.png

    image.png

    那么结合BeanFactory要实现相关的Bean增强操作,我们要做的行为就是两方面

    1. 创建相关的BeanPostProcessor,并注册到BeanFactory中
    2. BeanFactory在初始化Bean前后判断是否有相关BeanPostProcessor,如果有做相关的增强处理

      有了上面的分析,那么我们要实现具体的织入就需要来看看在对应前置和后置方法中我们要实现的功能

    image.png

    3.2 判断是否需要增强

      我们如何判断Bean对象是否需要增强呢?其实就是需要判断该Bean是否满足用户定义的切入点表达式。也就是我们需要简单Bean所属的类和所有方法。然后遍历Advisor。取出advisor中的Pointcut来匹配类和方法。

    image.png

    代码层面

        @Override
        public Object postProcessAfterInitialization(Object bean, String beanName) throws Throwable {
    
    		/*逻辑
    		1 判断Bean是否需要增强
    		2 创建代理来实现增强
    		*/
    
            //1 判断Bean是否需要增强
            List<Advisor> matchAdvisors = getMatchedAdvisors(bean, beanName);
    
    		// 2如有切面切中,创建代理来实现增强
    		if (CollectionUtils.isNotEmpty(matchAdvisors)) {
    			bean = this.createProxy(bean, beanName, matchAdvisors);
    		}
    
            return bean;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    image.png

    3.3 代理对象

      通过上面的分析如果Bean需要被增强,那么我们就需要创建Bean对应的代理对象了。代理模式:为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在调用者和目标对象之间起到中介的作用;

    image.png

      动态代理的实现方法有哪些?

    image.png

    JDK动态代理:

    在运行时,对接口创建代理对象

    image.png

    cglib动态代理:

    image.png

    3.4 代理实现层设计

      动态代理的实现方式有很多种,如何能够做到灵活的扩展呢?在这里我们同样可以通过 抽象面向接口编程来设计一套支持不同代理实现的代码

    image.png

      有了上面的设计,然后就是需要考虑代理对象的创建了。

    image.png

    3.5 增强逻辑实现

      代理对象搞定后我们需要考虑核心的问题就是怎么来实现我们要增强的逻辑呢?首先不管你用哪种方式来生成代理对象最终增强的逻辑代码是一样的。所以我们可以把这部分内容提炼出来。

    image.png

      然后具体的应用Advice增强实现的逻辑为:

    image.png

    注意此处用到了责任链模式

    	public static Object applyAdvices(Object target, Method method, Object[] args, List<Advisor> matchAdvisors,
    			Object proxy, BeanFactory beanFactory) throws Throwable {
    		// 这里要做什么?   需要获取相关案例代码的+V:boge3306 备注:手写Spring
    		// 1、获取要对当前方法进行增强的advice
    		List<Object> advices = AopProxyUtils.getShouldApplyAdvices(target.getClass(), method, matchAdvisors,
    				beanFactory);
    		// 2、如有增强的advice,责任链式增强执行
    		if (CollectionUtils.isEmpty(advices)) {
    			return method.invoke(target, args);
    		} else {
    			// 责任链式执行增强
    			AopAdviceChainInvocation chain = new AopAdviceChainInvocation(proxy, target, method, args, advices);
    			return chain.invoke();
    		}
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    然后我们前面的Creator要怎么使用AopProxy呢?这块我们可以通过工厂模式来处理

    image.png

    public interface AopProxyFactory {
    
    	AopProxy createAopProxy(Object bean, String beanName, List<Advisor> matchAdvisors, BeanFactory beanFactory)
    			throws Throwable;
    
    	/**
    	 * 获得默认的AopProxyFactory实例
    	 *    需要获取相关案例代码的+V:boge3306 备注:手写Spring
    	 * @return AopProxyFactory
    	 */
    	static AopProxyFactory getDefaultAopProxyFactory() {
    		return new DefaultAopProxyFactory();
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    到这儿,完整的增强逻辑就梳理通了

  • 相关阅读:
    三显智能氮气柜温度、湿度和氧含量控制介绍
    什么是网站SSL证书?SSL证书重要吗?
    【全开源】知识库文档系统(ThinkPHP+FastAdmin)
    OpenStack集群部署——计算节点neutron节点部署(三)
    dp背包解决组合问题——494. 目标和
    C程序函数调用&系统调用
    Java23种设计模式-结构型模式之桥接模式
    霍尔效应风扇驱动IC
    关于多线程“伪唤醒“的解释以及为什么要用while循环进行条件判断
    【LayerNorm 2d】 LayerNorm图解, torch代码实现, 用法
  • 原文地址:https://blog.csdn.net/qq_38526573/article/details/126724676