Spring源碼分析 AOP設計實現過程
設計理念
將分散在程序各處的橫切關注點剝離出來,並已集中的方式進行表達
AOP和繼承有些類似,前者重點考慮程序橫切邏輯,後者重點考慮縱向職責分派
AOP核心概念
Advice(通知)
-定義在連接點處的行爲,圍繞方法調用而進行注入
-Pointcut(切點)
-確定在哪些連接點處應用通知
Advisor()通知器
-組合Advice與Pointcut
AOP 代理
未使用代理如下
已使用代理如下
如圖所示
AOP代理可以 執行目標對象之前後都可以先執行指定好的通知器(切點和通知)
SpringAOP目標代理對象創建如下
- JDK動態代理 (代理接口)
- CGLIB(代理實現類)
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)