Spring源碼分析 AOP設計實現過程

Spring源碼分析 AOP設計實現過程

設計理念

將分散在程序各處的橫切關注點剝離出來,並已集中的方式進行表達
AOP和繼承有些類似,前者重點考慮程序橫切邏輯,後者重點考慮縱向職責分派

AOP核心概念

Advice(通知)
-定義在連接點處的行爲,圍繞方法調用而進行注入

-Pointcut(切點)
-確定在哪些連接點處應用通知

Advisor()通知器
-組合Advice與Pointcut

AOP 代理

未使用代理如下
通篇1

已使用代理如下

aop
如圖所示

AOP代理可以 執行目標對象之前後都可以先執行指定好的通知器(切點和通知)

SpringAOP目標代理對象創建如下

  • JDK動態代理 (代理接口)
  • CGLIB(代理實現類)

001
AOP代理源碼分析

public class ProxyFactoryBean extends ProxyCreatorSupport implements
		FactoryBean, BeanClassLoaderAware, BeanFactoryAware 
		
	    public Object getObject() throws BeansException {
	   		 //步驟1
			initializeAdvisorChain();
			//步驟2
			if (isSingleton())
				return getSingletonInstance();
			if (targetName == null)
				logger.warn("Using non-singleton proxies with singleton targets is often undesirable. Enable prototype proxies by setting the 'targetName' property.");
			return newPrototypeInstance();
		}
    }

ProxyFactoryBean是springAop底層實現源頭,構建其AOP代理
如上 步驟1
配置通知事件會調用getObject()方法,initializeAdvisorChain()會把配置的Adviser通知器方法加載到集合中,以便後續目標方法執行前後去集合中匹配,根據每個Adviser的pointcut去執行
步驟2 根據配置的 scope屬性,默認是single

緊接着分析 getSingletonInstance()方法獲取代理對象

private synchronized Object getSingletonInstance() {
		if (singletonInstance == null) {
			targetSource = freshTargetSource();
			if (autodetectInterfaces && getProxiedInterfaces().length == 0
					&& !isProxyTargetClass()) {
				Class targetClass = getTargetClass();
				if (targetClass == null)
					throw new FactoryBeanNotInitializedException(
							"Cannot determine target class for proxy");
						//1
				setInterfaces(ClassUtils.getAllInterfacesForClass(targetClass,
						proxyClassLoader));
			}
			super.setFrozen(freezeProxy);
			//2
			singletonInstance = getProxy(createAopProxy());
		}
		return singletonInstance;
	}
	
public interface AopProxy {

	public abstract Object getProxy();

	public abstract Object getProxy(ClassLoader classloader);
}

如上 //1 表示創建出來代理對象要實現代理接口
//2 通過工廠代理創建AopProxy接口,調用其getProxy,生成代理實例

AOP選擇動態代理和CGLIB 源碼如下

public class DefaultAopProxyFactory implements AopProxyFactory, Serializable {

	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())
				return new JdkDynamicAopProxy(config);
			else
				return CglibProxyFactory.createCglibProxy(config);
		} else {
			return new JdkDynamicAopProxy(config);
		}
	}

|

源碼分析

如果目標對象實現了接口,那麼Spring就會通過動態代理爲目標對象生成代理對象,否則通過CGLIB代理
代理模式作用是:爲其它對象提供一種代理以控制對這個對象的訪問

接着分析JDK動態代理源碼如下

final class JdkDynamicAopProxy implements AopProxy, InvocationHandler,
		Serializable {

		
		public Object getProxy(ClassLoader classLoader) {
		if (logger.isDebugEnabled())
			logger.debug((new StringBuilder())
					.append("Creating JDK dynamic proxy: target source is ")
					.append(advised.getTargetSource()).toString());
		Class proxiedInterfaces[] = AopProxyUtils
				.completeProxiedInterfaces(advised);
		findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
		//rs Proxy
		return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
	}

		
}

public interface InvocationHandler extends Callback {


	public abstract Object invoke(Object obj, Method method, Object aobj[])
			throws Throwable;
}

通過其源碼發現
如上rs Proxy真正使用JDK動態代理獲得代理實例,代理類需要繼承InvocationHandler接口,
InvocationHandler內部只有一個抽象方法invoke(參數1指代理類,參數2指代理方法,參數3指方法參數值)
Proxy.newProxyInstance(參數1 類加載器,參數2 動態代理對象實現了接口,參數3 指InvocationHandler 實例通過反射生成對象的實例)
由此可得
JDK動態代理 實現步驟
1.創建一個實現接口InvocationHandler的類嗎,它必須實現invoke方法
2.創建被代理類以及接口
3.通過proxy的靜態方法創建代理
4.通過代理調用方法

CGLIB 源碼如下

final class CglibAopProxy implements AopProxy, Serializable {

public Object getProxy(ClassLoader classLoader) {
		if (logger.isDebugEnabled())
			logger.debug((new StringBuilder())
					.append("Creating CGLIB proxy: target source is ")
					.append(advised.getTargetSource()).toString());
		try {
			Class rootClass = advised.getTargetClass();
			Assert.state(rootClass != null,
					"Target class must be available for creating a CGLIB proxy");
			Class proxySuperClass = rootClass;
			if (ClassUtils.isCglibProxyClass(rootClass)) {
				proxySuperClass = rootClass.getSuperclass();
				Class additionalInterfaces[] = rootClass.getInterfaces();
				Class arr$[] = additionalInterfaces;
				int len$ = arr$.length;
				for (int i$ = 0; i$ < len$; i$++) {
					Class additionalInterface = arr$[i$];
					advised.addInterface(additionalInterface);
				}

			}
			validateClassIfNecessary(proxySuperClass);
			Enhancer enhancer = createEnhancer();
			if (classLoader != null) {
				enhancer.setClassLoader(classLoader);
				if ((classLoader instanceof SmartClassLoader)
						&& ((SmartClassLoader) classLoader)
								.isClassReloadable(proxySuperClass))
					enhancer.setUseCache(false);
			}
			enhancer.setSuperclass(proxySuperClass);
			enhancer.setStrategy(new UndeclaredThrowableStrategy(java / lang
					/ reflect / UndeclaredThrowableException));
			enhancer.setInterfaces(AopProxyUtils
					.completeProxiedInterfaces(advised));
			enhancer.setInterceptDuringConstruction(false);
			Callback callbacks[] = getCallbacks(rootClass);
			enhancer.setCallbacks(callbacks);
			enhancer.setCallbackFilter(new ProxyCallbackFilter(advised
					.getConfigurationOnlyCopy(), fixedInterceptorMap,
					fixedInterceptorOffset));
			Class types[] = new Class[callbacks.length];
			for (int x = 0; x < types.length; x++)
				types[x] = callbacks[x].getClass();

			enhancer.setCallbackTypes(types);
			Object proxy;
			//結果
			if (constructorArgs != null)
				proxy = enhancer.create(constructorArgTypes, constructorArgs);
			else
				proxy = enhancer.create();
			return proxy;
		} catch (CodeGenerationException ex) {
			throw new AopConfigException(
					(new StringBuilder())
							.append("Could not generate CGLIB subclass of class [")
							.append(advised.getTargetClass())
							.append("]: ")
							.append("Common causes of this problem include using a final class or a non-visible class")
							.toString(), ex);
		} catch (IllegalArgumentException ex) {
			throw new AopConfigException(
					(new StringBuilder())
							.append("Could not generate CGLIB subclass of class [")
							.append(advised.getTargetClass())
							.append("]: ")
							.append("Common causes of this problem include using a final class or a non-visible class")
							.toString(), ex);
		} catch (Exception ex) {
			throw new AopConfigException("Unexpected AOP exception", ex);
		}
	}

}

如上結果 通過 Enhancer.create生成代理實例,其通過Enhancer 字節碼類構建類的接口、類型、類回調等參數
最終會的代理實例對象

總結:

本篇文章主要闡述 AOP攔截觸發器執行過程、AOP代理實現的兩種方式

作者簡介:張程 技術研究

更多文章請關注微信公衆號:zachary分解獅 (frankly0423)

在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章