• spring5.0源码解析 Aop 02


    建立 AopProxy对象

    设计原理

    在spring 的 Aop模块中,是通过配置和调用Spring的ProxyFactoryBean来完成这个任务的,在 ProxyFactoryBean 中,封装了主要代理对象的生成过程,这个过程由JDK的Proxy和CGLibL两种方式实现

    在这里插入图片描述
    在这个 类继承关系中,可以看到完成 AOP应用的类,比如AspectJProxyFactory、TransactionProxyFactoryBean , 具体的对象的生成分别由 ProxyFactoryBean,AspectJProxyFactory和ProxyFactory来完成,**ProxyFactoryBean和ProxyFactory都提供了AOP功能的封装,只是使用ProxyFactoryBean可以在Ioc容器中完成声明式配置,而是用ProxyFactory 则需要编程式使用Aop的功能

    ProxyConfig

    用于创建代理的配置的方便超类,以确保所有代理创建者具有一致的属性

    	// 是否直接代理目标类,为不是代理特定的接口
    	private boolean proxyTargetClass = false;
    
    	// 标记是否对代理进行优化。启动优化通常意味着在代理对象被创建后,增强的修改将不会生效,因此默认值为false。
    	private boolean optimize = false;
    
    	//该属性用于空值生成的代理对象是否可以强制转型为Advised,默认值为false,表示任何生成的代理对象都可以强制转换成Advised,true是不可以,可以通过Adviced查询代理对象的一些状态
    	boolean opaque = false;
    
    	// 标记代理对象是否应该被aop框架通过AopContext以ThreadLocal的形式暴露出去。
    	// 当一个代理对象需要调用它自己的另外一个代理方法时,这个属性将非常有用。默认是是false,以避免不必要的拦截。
    	boolean exposeProxy = false;
    
    	// 标记该配置是否需要被冻结,如果被冻结,将不可以修改增强的配置。
    	// 如果该值为true,那么代理对象的生成的各项信息配置完成,则不容许更改,如果ProxyFactory设置完毕,该值为true,则不能对Advice进行改动,可以优化代理对象生成的性能。默认情况下该值为false
    	private boolean frozen = false;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    AdvisedSupport

    可以将他看成其子类创建Aop代理对象的一个辅助类。

    配置当前代理的Adivsiors
    配置当前代理的目标对象
    配置当前代理的接口
    提供getInterceptorsAndDynamicInterceptionAdvice方法用来获取对应代理方法对应有效的拦截器链

    ProxyFactoryBean

    getObject返回此工厂Aop代理实例

    ProxyFactoryBean 实现了 FactoryBean getObject返回此工厂Aop代理实例

    // 创建此工厂返回的AOP代理实例。
    	@Override
    	@Nullable
    	public Object getObject() throws BeansException {
    		// 初始化通知器链
    		initializeAdvisorChain();
    		// 这里对singleton和prititype类型进行了区分,生成对象的proxy
    		if (isSingleton()) {
    			return getSingletonInstance();
    		}
    		else {
    			if (this.targetName == null) {
    				logger.info("Using non-singleton proxies with singleton targets is often undesirable. " +
    						"Enable prototype proxies by setting the 'targetName' property.");
    			}
    			return newPrototypeInstance();
    		}
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    proxyFactory

    在专栏前面的文章介绍了 使用ProxyFactoryBean 实现获取Aop代理对象。 ProxyFactoryBean 与 proxyFactory 的实现原理是一样的 ,不过是对 拦截器、切入点进行整合,通过递归的形式生成代理对象的过程,只是他们两个在最外层的表现上有所不同。

    proxyFactory 是 ProxyCreatorSupport 的子类,proxyFactory 获取代理对象也是通过 getProxy方法为入口,由 getAopProxyFactory 完成 , 而 ProxyCreatorSupport 也继承了 AdvisedSupport 具有了 通知和切入点的支持

    	public <T> T getProxy() {
    		return (T) createAopProxy().getProxy();
    	}
    	protected final synchronized AopProxy createAopProxy() {
    		if (!this.active) {
    			activate();
    		}
    		// getAopProxyFactory 获取的是 DefaultAopProxyFactory 对象
    		return getAopProxyFactory().createAopProxy(this);
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    AspectProxyFactory、 proxyFactory 、 ProxyFactoryBean 的区别

    在这里插入图片描述

    • proxyFactory 这种是硬编码的方式,可以脱离spring直接使用。
    • AspectProxyFactory 实现了 @AspectJ 注解的形式 我们只需要配置切面、通知、切点表达式就能自动的实现切入的效果
    • ProxyFactoryBean 是创建AOP的最基本的方式。是将我们的AOP和IOC融合起来,而ProxyFactory 则是只能通过代码硬编码进行编写 一般都是给spring自己使用。

    initializeAdvisorChain 初始化通知链

    // 初始化通知链
    	private synchronized void initializeAdvisorChain() throws AopConfigException, BeansException {
    		// 判断是否初始化过 , 通知链只出初始化一次
    		if (this.advisorChainInitialized) {
    			return;
    		}
    
    		if (!ObjectUtils.isEmpty(this.interceptorNames)) {
    			if (this.beanFactory == null) {
    				throw new IllegalStateException("No BeanFactory available anymore (probably due to serialization) " +
    						"- cannot resolve interceptor names " + Arrays.asList(this.interceptorNames));
    			}
    
    			// Globals can't be last unless we specified a targetSource using the property...
    			if (this.interceptorNames[this.interceptorNames.length - 1].endsWith(GLOBAL_SUFFIX) &&
    					this.targetName == null && this.targetSource == EMPTY_TARGET_SOURCE) {
    				throw new AopConfigException("Target required after globals");
    			}
    
    			// Materialize interceptor chain from bean names.
    			// 从bean名称具体化拦截器链。
    			for (String name : this.interceptorNames) {
    				// 如果拦截器name 以  * 号结尾
    				if (name.endsWith(GLOBAL_SUFFIX)) {
    					if (!(this.beanFactory instanceof ListableBeanFactory)) {
    						throw new AopConfigException(
    								"Can only use global advisors or interceptors with a ListableBeanFactory");
    					}
    					addGlobalAdvisors((ListableBeanFactory) this.beanFactory,
    							name.substring(0, name.length() - GLOBAL_SUFFIX.length()));
    				}
    
    				else {
    					// If we get here, we need to add a named interceptor.
    					// We must check if it's a singleton or prototype.
    					//需要添加一个命名拦截器。必须检查它是单体还是原型。
    					Object advice;
    					if (this.singleton || this.beanFactory.isSingleton(name)) {
    						// Add the real Advisor/Advice to the chain.
    						advice = this.beanFactory.getBean(name);
    					}
    					else {
    						// It's a prototype Advice or Advisor: replace with a prototype.
    						// Avoid unnecessary creation of prototype bean just for advisor chain initialization.
    						advice = new PrototypePlaceholderAdvisor(name);
    					}
    					//将给定的advice, advisor或对象添加到拦截器列表中。
    					addAdvisorOnChainCreation(advice);
    				}
    			}
    		}
    
    		this.advisorChainInitialized = true;
    	}
    
    • 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
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54

    getSingletonInstance 生成单例的代理对象

    getSingletonInstance 这个方法是 proxyFactoryBean生成AopProxy代理对象的调用接口。代理对象会封装对target目标对象的调用,也就是说针对target对象的调用行为会被这里生成的代理对象所拦截,

    // 返回这个类的代理对象的单例实例,如果尚未创建,则延迟创建。
    	private synchronized Object getSingletonInstance() {
    		if (this.singletonInstance == null) {
    			// 被代理的目标对象
    			this.targetSource = freshTargetSource();
    			if (this.autodetectInterfaces && getProxiedInterfaces().length == 0 && !isProxyTargetClass()) {
    				// Rely on AOP infrastructure to tell us what interfaces to proxy.
    				// 依靠AOP基础设施告诉我们代理的接口。
    				Class<?> targetClass = getTargetClass();
    				if (targetClass == null) {
    					throw new FactoryBeanNotInitializedException("Cannot determine target class for proxy");
    				}
    				// 设置代理对象的接口
    				setInterfaces(ClassUtils.getAllInterfacesForClass(targetClass, this.proxyClassLoader));
    			}
    			// 初始化共享单例实例。
    			super.setFrozen(this.freezeProxy);
    			// 生成具体的代理对象
    			this.singletonInstance = getProxy(createAopProxy());
    		}
    		return this.singletonInstance;
    	}
    	// 获取代理对象
    protected Object getProxy(AopProxy aopProxy) {
    		return aopProxy.getProxy(this.proxyClassLoader);
    	}
    
    • 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

    AopProxy

    spring 利用 AopProxy 接口类把Aop代理对象的实现与框架其他部分有效的分开,他有两个子类 CglibAopProxy 和 JdkDynamicAopProxy 分别采用 CGLIB和 JDK来生成代理对象。

    生成 AopProxy 是通过 AopProxyFactory来实现的,至于生成什么样的代理对象封装在 AdvisedSupport 中,也是 ProxyFactoryBean 的父类

    // 通过 AopProxyFactory 生成 AopProxy
    	protected final synchronized AopProxy createAopProxy() {
    		if (!this.active) {
    			activate();
    		}
    		return getAopProxyFactory().createAopProxy(this);
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    DefaultAopProxyFactory.createAopProxy 方法 根据 AdvisedSupport 生成AopProxy 这里决定了使用CGLIB还是Jdk的的方式

    @Override
    	public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
    		if (!NativeDetector.inNativeImage() &&
    				(config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config))) {
    			Class<?> targetClass = config.getTargetClass();
    			if (targetClass == null) {
    				throw new AopConfigException("TargetSource cannot determine target class: " +
    						"Either an interface or a target is required for proxy creation.");
    			}
    			// 如果targetClass是接口类,使用Jdk 来生成
    			if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
    				return new JdkDynamicAopProxy(config);
    			}
    			// 使用Cglib 生成
    			return new ObjenesisCglibAopProxy(config);
    		}
    		else {
    			return new JdkDynamicAopProxy(config);
    		}
    	}
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    在AopProxy代理对象生成过程中,首先要从AdvisedSupport对象中取得配置的目标对象,在完成目标对象的检查后,根据配置情况来决定使用什么方式来创建AopProxy代理对象。

  • 相关阅读:
    Maven assembly多模块多环境(dev|test|prod)定制化打包SpringBoot项目详解
    服务注册发现 springcloud netflix eureka
    【大数据存储技术】思考题及参考答案
    Pytorch从零开始实现Vision Transformer (from scratch)
    如何将所有公司的校招信息一网打尽?
    【Maven】使用maven profile 动态激活不同环境、依赖打包部署
    【Harmony OS】【ArkUI】ets开发 图形与动画绘制
    什么是架构?
    线控制动「放量」上攻
    illustrator一些报错的原因
  • 原文地址:https://blog.csdn.net/qq_44808472/article/details/126254219