Spring AOP的實現:建立AopProxy代理物件
前面我們講述了AOP的基本知識以及在Spring AOP機制中的一些基本的資料結構及其功能。下面開始正式的講述Spring AOP的實現部分。
來看一下這個以ProxyFactory為中心的繼承關係圖
可以將ProxyConfig看做是一個數據基類,這個基類為ProxyFactoryBean這樣的子類提供了屬性的配置。而AdvisedSupport則是實現了對於通知器和通知的相關操作。
在分析Spring AOP的實現原理中。原書是以ProxyFactoryBean的實現作為例子的。通過這個工程Bean,生產出了我們需要的AopProxy代理物件。
那麼書上首先給了我們這樣的關於ProxyFactoryBean的配置方法。
我們可以看到,我們需要給我們的ProxyFactoryBean配置一個通知器,這個通知器是它的interceptorNames屬性。當然還需要配置proxyInterfaces,這個是目標介面,也就是被代理的介面。target ,目標物件。
值得注意一點,雖然這裡聲明瞭interceptorNames屬性,但是這個不是之後我會提到的攔截器。這個屬性宣告的是供AOP應用配置通知器的地方,需要為target目標物件生成Proxy代理物件,從而為AOP橫切面的編織做好準備工作。
在ProxyFactoryBean中,它的AOP實現需要依賴JDK或者CGLIB提供的Proxy特性(也就是我前面所說的代理模式)。從FactoryBean中獲取物件,是使用getObject()方法來完成的
@Override public Object getObject() throws BeansException { initializeAdvisorChain(); if (isSingleton()) { return getSingletonInstance(); } else { if (this.targetName == null) { logger.warn("Using non-singleton proxies with singleton targets is often undesirable. " + "Enable prototype proxies by setting the 'targetName' property."); } return newPrototypeInstance(); } }
首先要對通知器鏈進行初始化操作,通知器鏈封裝了一系列的攔截器,這些攔截器都要從配置中讀取,然後為代理物件的生成做好準備。Spring中有singleton和prototype型別這兩種不同的bean,所以這裡對代理物件的生成需要做一個區分。
現在來看一下initializeAdvisorChain();這個方法,它為Proxy代理物件配置Advistor鏈是在這個方法中完成的。從程式碼中我們可以看到,從ListableBeanFactory中取得相應的通知器並把這些通知器加入到通知器鏈中。
生成singleton代理物件是在getSingletonInstance()中實現的。
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.
Class<?> targetClass = getTargetClass();
if (targetClass == null) {
throw new FactoryBeanNotInitializedException("Cannot determine target class for proxy");
}
setInterfaces(ClassUtils.getAllInterfacesForClass(targetClass, this.proxyClassLoader));
}
// Initialize the shared singleton instance.
super.setFrozen(this.freezeProxy);
this.singletonInstance = getProxy(createAopProxy());
}
return this.singletonInstance;
}
首先需要設定代理物件的介面
setInterfaces(ClassUtils.getAllInterfacesForClass(targetClass, this.proxyClassLoader));
之後我們會使用ProxyFactory來生成我們需要的Proxy。
this.singletonInstance = getProxy(createAopProxy());
protected Object getProxy(AopProxy aopProxy) {
return aopProxy.getProxy(this.proxyClassLoader);
}
這裡使用的時候AopProxy的getProxy()方法生成代理物件。AopProxy的獲得方法是由
org.springframework.aop.framework.ProxyCreatorSupport.createAopProxy()
實現的
protected final synchronized AopProxy createAopProxy() {
if (!this.active) {
activate();
}
return getAopProxyFactory().createAopProxy(this);
}
在DefaultAopProxyFactory中建立AopProxy
@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);
}
}
接下里具體的代理物件的生成可以由兩種方式。AOP代理物件的生成,是根據我們的目標物件的型別。如果是介面類,那麼就使用JDK來生成代理物件,否則Spring使用CGLIB來生成目標物件的代理物件。當返回的是JDKDynamicAopProxy物件時。它的getProxy()方法如下所示
@Override
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);
return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
}
在這個地方我們看到了
Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
這就是我之前的一篇部落格https://blog.csdn.net/qq1641530151/article/details/83036756
中提到的動態連結。這裡我們也可以看到,spring的底層實際上也呼叫了jdk的代理模式。
這個地方為我們返回了目標物件的代理物件。
關於CGLIB對於代理物件的生成方式,是類似的。書上也有相應的程式碼。
下次我將來講述關於Spring AOP的攔截器的呼叫。