SpringAop源碼分析(基於註解)三:建立代理對象

在上篇文章SpringAop源碼分析(基於註解)二:篩選通知器中,咱們對AOP中通知的建立和篩選過程進行了分析,本章咱們一塊兒來看看,AOP是怎麼建立代理對象的。java

咱們先回到Bean初始化以後,調用BeanPostProcessor後置處理器的地方。緩存

//AbstractAutoProxyCreator.java

//在Bean初始化以後回調
@Override
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) throws BeansException {
	if (bean != null) {
		Object cacheKey = getCacheKey(bean.getClass(), beanName);
		//判斷緩存中是否有
		if (!this.earlyProxyReferences.contains(cacheKey)) {
			// 沒有,爲 bean 生成代理對象
			return wrapIfNecessary(bean, beanName, cacheKey);
		}
	}
	return bean;
}
複製代碼

wrapIfNecessary代碼:ide

//AbstractAutoProxyCreator.java

protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
	if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
		return bean;
	}
	if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
		return bean;
	}

	/* * 若是是基礎設施類(Pointcut、Advice、Advisor 等接口的實現類),或是應該跳過的類, * 則不該該生成代理,此時直接返回 bean */
	if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
		this.advisedBeans.put(cacheKey, Boolean.FALSE);
		return bean;
	}

	// Create proxy if we have advice.
<1>	// 返回匹配當前 bean 的全部的通知器 advisor、advice、interceptor
	Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
	if (specificInterceptors != DO_NOT_PROXY) {
		this.advisedBeans.put(cacheKey, Boolean.TRUE);
		// 核心!建立代理對象
<2>		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>處代碼,如今有了合適的通知器,咱們要爲當前Bean建立代理對象,把通知器(Advisor)所持有的通知(Advice)織入到 bean 的某些方法先後。源碼分析

看代碼:post

//AbstractAutoProxyCreator.java

protected Object createProxy(Class<?> beanClass, @Nullable String beanName, @Nullable Object[] specificInterceptors, TargetSource targetSource) {

	if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
		AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
	}

	//建立代理工廠
	ProxyFactory proxyFactory = new ProxyFactory();
	proxyFactory.copyFrom(this);

	//proxyTargetClass是 @EnableAspectJAutoProxy 的屬性之一
	//true -> 強制使用CGLIB代理
	if (!proxyFactory.isProxyTargetClass()) {
		//false
		if (shouldProxyTargetClass(beanClass, beanName)) {
			proxyFactory.setProxyTargetClass(true);
		}
		else {
			//檢測 beanClass 是否實現了接口,若未實現,則將
			//proxyFactory 的成員變量 proxyTargetClass 設爲 true
			evaluateProxyInterfaces(beanClass, proxyFactory);
		}
	}
    
        //封裝proxyFactory
	Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
	proxyFactory.addAdvisors(advisors);
	proxyFactory.setTargetSource(targetSource);
	customizeProxyFactory(proxyFactory);

	proxyFactory.setFrozen(this.freezeProxy);
	if (advisorsPreFiltered()) {
		proxyFactory.setPreFiltered(true);
	}

	// 建立並獲取代理對象
	return proxyFactory.getProxy(getProxyClassLoader());
	}
複製代碼

這裏咱們主要看下核心邏輯:優化

  • 建立代理工廠 ProxyFactory
  • 判斷使用JDK仍是CGLIB
  • 封裝ProxyFactory
  • 建立並獲取代理對象

這裏的 isProxyTargetClass() 其實就是咱們前面用的註解@EnableAspectJAutoProxy的屬性之一,當其爲true時,強制使用CGLIB代理。ui

下面咱們接着看建立代理的代碼:this

//ProxyFactory.java

public Object getProxy(@Nullable ClassLoader classLoader) {
	return createAopProxy().getProxy(classLoader);
}
複製代碼

這段方法有兩個方法調用:lua

  • createAopProxy()
    建立 AopProxy 實現類對象
  • getProxy(classLoader)
    建立代理對象

咱們先來看下createAopProxy():spa

//DefaultAopProxyFactory.java

public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
	//if中的3個條件
	//一、 config.isOptimize() - 是否須要優化
	//二、 config.isProxyTargetClass() - 檢測 proxyTargetClass 的值
	//三、 hasNoUserSuppliedProxyInterfaces(config) - 目標 bean 是否實現了接口
	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)) {
			//建立JdkDynamicAopProxy
			return new JdkDynamicAopProxy(config);
		}
		//建立CglibAopProxy
		return new ObjenesisCglibAopProxy(config);
	}
	else {
		//建立JdkDynamicAopProxy
		return new JdkDynamicAopProxy(config);
	}
	}
複製代碼

最終調用的是DefaultAopProxyFactory#createAopProxy(...)方法,經過這個方法建立AopProxy 的實現類,如: JdkDynamicAopProxy,而後根據這個實現類再建立代理對象。

咱們以JdkDynamicAopProxy爲例,看下getProxy(classLoader):

//JdkDynamicAopProxy.java

public Object getProxy() {
    return getProxy(ClassUtils.getDefaultClassLoader());
}

public Object getProxy(ClassLoader classLoader) {
    if (logger.isDebugEnabled()) {
        logger.debug("Creating JDK dynamic proxy: target source is " + this.advised.getTargetSource());
    }
    Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
    findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
    
    // 調用 newProxyInstance 建立代理對象
    return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
}
複製代碼

直接看代碼最後一行,最終調用 Proxy.newProxyInstance 方法建立代理對象。

參考:
www.tianxiaobo.com/2018/06/20/…

相關文章
相關標籤/搜索