天天看點

spring5.0源碼解析 Aop 02建立 AopProxy對象AspectProxyFactory、 proxyFactory 、 ProxyFactoryBean 的差別

spring5.0源碼解析 Aop 02

  • 建立 AopProxy對象
    • 設計原理
      • ProxyConfig
      • AdvisedSupport
      • ProxyFactoryBean
      • getObject傳回此工廠Aop代理執行個體
      • proxyFactory
  • AspectProxyFactory、 proxyFactory 、 ProxyFactoryBean 的差別
        • initializeAdvisorChain 初始化通知鍊
        • getSingletonInstance 生成單例的代理對象
      • AopProxy

建立 AopProxy對象

設計原理

在spring 的 Aop子產品中,是通過配置和調用Spring的ProxyFactoryBean來完成這個任務的,在 ProxyFactoryBean 中,封裝了主要代理對象的生成過程,這個過程由JDK的Proxy和CGLibL兩種方式實作

spring5.0源碼解析 Aop 02建立 AopProxy對象AspectProxyFactory、 proxyFactory 、 ProxyFactoryBean 的差別

在這個 類繼承關系中,可以看到完成 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;
           

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();
		}
	}
           

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);
	}
           

AspectProxyFactory、 proxyFactory 、 ProxyFactoryBean 的差別

spring5.0源碼解析 Aop 02建立 AopProxy對象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;
	}
           

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);
	}
           

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);
	}
           

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);
		}
	}

           

在AopProxy代理對象生成過程中,首先要從AdvisedSupport對象中取得配置的目标對象,在完成目标對象的檢查後,根據配置情況來決定使用什麼方式來建立AopProxy代理對象。