SpringAop源碼情操陶冶-AspectJAwareAdvisorAutoProxyCreator


本文將對SpringAop中如何為AspectJ切面類創建自動代理的過程作下簡單的分析,閱讀本文前需要對AOP的Spring相關解析有所了解,具體可見Spring源碼情操陶冶-AOP之ConfigBeanDefinitionParser解析器

官方注釋

注釋內容如下

/**
 * {@link org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator}
 * subclass that exposes AspectJ's invocation context and understands AspectJ's rules
 * for advice precedence when multiple pieces of advice come from the same aspect.
 *
 * @author Adrian Colyer
 * @author Juergen Hoeller
 * @author Ramnivas Laddad
 * @since 2.0
 */

從注釋上可知此類是org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator抽象類的繼承類,主要為AspectJ切面服務。具體的針對如何創建代理,肯定是在父類中實現了,我們在此研究下父類。

AbstractAutoProxyCreator-AOP代理實現的抽象父類

繼承結構上為extends ProxyProcessorSupport implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware,而其中的SmartInstantiationAwareBeanPostProcessor是beanPostProcessor接口的子類,此處注意下此接口。下面分析的內容建立在spring在實例化bean對象的時候會調用beanPostProcessor的公有接口。

AbstractAutoProxyCreator#postProcessAfterInitialization()-創建代理的入口函數

先奉上源碼內容如下

	/**
	 * Create a proxy with the configured interceptors if the bean is
	 * identified as one to proxy by the subclass.
	 * @see #getAdvicesAndAdvisorsForBean
	 */
	@Override
	public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
		if (bean != null) {
			Object cacheKey = getCacheKey(bean.getClass(), beanName);
			// 如果緩存中不存在則調用wrapIfNecessary()方法創建代理
			if (!this.earlyProxyReferences.contains(cacheKey)) {
				return wrapIfNecessary(bean, beanName, cacheKey);
			}
		}
		return bean;
	}

以上調用的是beanPostProcessor接口的postProcessAfterInitialization(Object bean,String beanName)的方法,其一般是bean對象被實例化的最后一步操作的,此處避而不談了,我們轉而查看wrapIfNecessary()的內部是如何操作的

AbstractAutoProxyCreator#wrapIfNecessary()-創建代理對象幫助函數

	/**
	 * Wrap the given bean if necessary, i.e. if it is eligible for being proxied.
	 * @param bean the raw bean instance
	 * @param beanName the name of the bean
	 * @param cacheKey the cache key for metadata access
	 * @return a proxy wrapping the bean, or the raw bean instance as-is
	 */
	protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
	    // 查看緩存是否存在此bean
		if (beanName != null && this.targetSourcedBeans.contains(beanName)) {
			return bean;
		}
		if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
			return bean;
		}
		// Advice/Advisor/AopInfrastructureBean接口的beanClass不進行代理以及對beanName為aop內的切面名也不進行代理,此處可查看子類復寫的sholdSkip()方法
		if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
			this.advisedBeans.put(cacheKey, Boolean.FALSE);
			return bean;
		}

		// Create proxy if we have advice.
		// 查找對代理類相關的advisor對象集合,此處就與ponit-cut表達式有關了
		Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
		// 對相應的advisor不為空才采取代理
		if (specificInterceptors != DO_NOT_PROXY) {
			this.advisedBeans.put(cacheKey, Boolean.TRUE);
			// 調用createProxy()方法創建真正的代理對象
			Object proxy = createProxy(
					bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
			this.proxyTypes.put(cacheKey, proxy.getClass());
			return proxy;
		}

		this.advisedBeans.put(cacheKey, Boolean.FALSE);
		return bean;
	

對上述的源碼分析作下簡單的總結

  1. 首先對Advice/Advisor/AopInfrastructureBean接口的實現類不進行代理操作;對beanName為aspectName的bean對象也不采取代理操作

  2. 再而需要查找beanClass有幾個advisor與之相關聯,這當然與每個Advisor接口內的PointCut對象對應的表達式expression有關。只有關聯的Advisor個數不為0,才可采取代理(此處查找Advisor關聯個數的源碼讀者可自行分析AspectJAwareAdvisorAutoProxyCreator#shouldSkip()方法)

  3. 真正的代理操作是由AbstractAutoProxyCreator#createProxy()內部方法實現

AbstractAutoProxyCreator#createProxy()-創建真正的AOP代理

對符合條件的beanClass進行相應的代理操作,簡單看下源碼

	/**
	 * Create an AOP proxy for the given bean.
	 * @param beanClass the class of the bean
	 * @param beanName the name of the bean
	 * @param specificInterceptors the set of interceptors that is
	 * specific to this bean (may be empty, but not null)
	 * @param targetSource the TargetSource for the proxy,
	 * already pre-configured to access the bean
	 * @return the AOP proxy for the bean
	 * @see #buildAdvisors
	 */
	protected Object createProxy(
			Class<?> beanClass, String beanName, Object[] specificInterceptors, TargetSource targetSource) {

		if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
			AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
		}
		// 創建AOP代理工廠,拷貝相同的屬性
		ProxyFactory proxyFactory = new ProxyFactory();
		proxyFactory.copyFrom(this);
		// 是否采用動態代理
		if (!proxyFactory.isProxyTargetClass()) {
			if (shouldProxyTargetClass(beanClass, beanName)) {
				proxyFactory.setProxyTargetClass(true);
			}
			else {
				// 查看beanClass對應的類是否含有InitializingBean.class/DisposableBean.class/Aware.class接口,無則采用靜態代理,有則采用動態代理
				evaluateProxyInterfaces(beanClass, proxyFactory);
			}
		}
		// 獲得所有關聯的Advisor集合
		Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
		for (Advisor advisor : advisors) {
			proxyFactory.addAdvisor(advisor);
		}
		// 此處的targetSource一般為SingletonTargetSource
		proxyFactory.setTargetSource(targetSource);
		customizeProxyFactory(proxyFactory);

		proxyFactory.setFrozen(this.freezeProxy);
		// 是否設置預過濾模式,此處針對本文為true
		if (advisorsPreFiltered()) {
			proxyFactory.setPreFiltered(true);
		}

		return proxyFactory.getProxy(getProxyClassLoader());
	}

對以上的源碼也作下簡單的總結

  1. 采用ProxyFactory對象來創建代理對象

  2. 如果AOP沒有指定proxyTargetClass屬性,則針對beanClass含有非InitializingBean/DisposableBean/Aware接口的bean采用靜態代理,反之采用動態代理

  3. ProxyFactory創建代理對象前也需要設置與beanClass相關聯的advisor集合

ProxyFactory#getProxy()-最終創建代理類

public Object getProxy(ClassLoader classLoader) {
		return createAopProxy().getProxy(classLoader);
	}

以上的源碼我們只需要關注createAopProxy()方法即可,此處我們直接查看DefaultAopProxyFactory#createAopProxy()源碼,參考如下

	@Override
	public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
		if (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.");
			}
			if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
				return new JdkDynamicAopProxy(config);
			}
			return new ObjenesisCglibAopProxy(config);
		}
		else {
			return new JdkDynamicAopProxy(config);
		}
	}

上述源碼很簡單,默認是采用JDK靜態代理,對beanClass為非接口實現類采取CGLIB動態代理

小結

  • 循序漸進的分析的總結見以上的各部分小結,我們只需要知道AOP代理的beanClass必須有相應的Advisor接口與之綁定,才會創建AOP代理

  • 創建的代理類無非是JDK代理抑或是CGLIB代理,但是具體關聯的Advisor集合的處理邏輯見下文講解


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM