下面我們來看看Spring的AOP的一些相關(guān)代碼是怎么得到Proxy的,讓我們我們先看看AOP和Spring AOP的一些基本概念:
Advice:
通知,制定在連接點做什么,在Sping中,他主要描述Spring圍繞方法調(diào)用注入的額外的行為,Spring提供的通知類型有:
before advice,AfterReturningAdvice,ThrowAdvice,MethodBeforeAdvice,這些都是Spring AOP定義的接口類,具體的動作實現(xiàn)需要用戶程序來完成。
Pointcut:
切點,其決定一個advice應(yīng)該應(yīng)用于哪個連接點,也就是需要插入額外處理的地方的集合,例如,被某個advice作為目標(biāo)的一組方法。Spring pointcut通常意味著標(biāo)示方法,可以選擇一組方法調(diào)用作為pointcut,Spring提供了具體的切點來給用戶使用,比如正則表達式切點 JdkRegexpMethodPointcut通過正則表達式對方法名進行匹配,其通過使用 AbstractJdkRegexpMethodPointcut中的對MethodMatcher接口的實現(xiàn)來完成pointcut功能:
- public final boolean matches(Method method, Class targetClass) {
-
- String patt = method.getDeclaringClass().getName() + "." + method.getName();
- for (int i = 0; i < this.patterns.length; i++) {
-
- boolean matched = matches(patt, i);
- if (matched) {
- for (int j = 0; j < this.excludedPatterns.length; j++) {
- boolean excluded = matchesExclusion(patt, j);
- if(excluded) {
- return false;
- }
- }
- return true;
- }
- }
- return false;
- }
public final boolean matches(Method method, Class targetClass) {
//這里通過放射得到方法的全名
String patt = method.getDeclaringClass().getName() + "." + method.getName();
for (int i = 0; i < this.patterns.length; i++) {
// 這里是判斷是否和方法名是否匹配的代碼
boolean matched = matches(patt, i);
if (matched) {
for (int j = 0; j < this.excludedPatterns.length; j++) {
boolean excluded = matchesExclusion(patt, j);
if(excluded) {
return false;
}
}
return true;
}
}
return false;
}
在JDKRegexpMethodPointcut中通過JDK中的正則表達式匹配來完成pointcut的最終確定:
- protected boolean matches(String pattern, int patternIndex) {
- Matcher matcher = this.compiledPatterns[patternIndex].matcher(pattern);
- return matcher.matches();
- }
protected boolean matches(String pattern, int patternIndex) {
Matcher matcher = this.compiledPatterns[patternIndex].matcher(pattern);
return matcher.matches();
}
Advisor:
當(dāng)我們完成額外的動作設(shè)計(advice)和額外動作插入點的設(shè)計(pointcut)以后,我們需要一個對象把他們結(jié)合起來,這就是通知器 - advisor,定義應(yīng)該在哪里應(yīng)用哪個通知。Advisor的實現(xiàn)有:DefaultPointcutAdvisor他有兩個屬性advice和 pointcut來讓我們配置advice和pointcut。
接著我們就可以通過ProxyFactoryBean來配置我們的代理對象和方面行為,在ProxyFactoryBean中有interceptorNames來配置已經(jīng)定義好的通知器-advisor,雖然這里的名字叫做interceptNames,但實際上是供我們配置advisor的地方,具體的代理實現(xiàn)通過JDK 的Proxy或者CGLIB來完成。因為ProxyFactoryBean是一個FactoryBean,在ProxyFactoryBean中我們通過getObject()可以直接得到代理對象:
- public Object getObject() throws BeansException {
-
- initializeAdvisorChain();
- if (isSingleton()) {
-
- return getSingletonInstance();
- }
- else {
- .......
-
- return newPrototypeInstance();
- }
- }
public Object getObject() throws BeansException {
//這里初始化通知器鏈
initializeAdvisorChain();
if (isSingleton()) {
//根據(jù)定義需要生成單件的Proxy
return getSingletonInstance();
}
else {
.......
//這里根據(jù)定義需要生成Prototype類型的Proxy
return newPrototypeInstance();
}
}
我們看看怎樣生成單件的代理對象:
- private synchronized Object getSingletonInstance() {
- if (this.singletonInstance == null) {
- this.targetSource = freshTargetSource();
- if (this.autodetectInterfaces && getProxiedInterfaces().length == 0 && !isProxyTargetClass()) {
-
- setInterfaces(ClassUtils.getAllInterfacesForClass(this.targetSource.getTargetClass()));
- }
-
- super.setFrozen(this.freezeProxy);
-
- this.singletonInstance = getProxy(createAopProxy());
-
-
- addListener(this);
- }
- return this.singletonInstance;
- }
-
-
- protected Object getProxy(AopProxy aopProxy) {
- return aopProxy.getProxy(this.beanClassLoader);
- }
private synchronized Object getSingletonInstance() {
if (this.singletonInstance == null) {
this.targetSource = freshTargetSource();
if (this.autodetectInterfaces && getProxiedInterfaces().length == 0 && !isProxyTargetClass()) {
// 這里設(shè)置代理對象的接口
setInterfaces(ClassUtils.getAllInterfacesForClass(this.targetSource.getTargetClass()));
}
// Eagerly initialize the shared singleton instance.
super.setFrozen(this.freezeProxy);
// 注意這里的方法會使用ProxyFactory來生成我們需要的Proxy
this.singletonInstance = getProxy(createAopProxy());
// We must listen to superclass advice change events to recache the singleton
// instance if necessary.
addListener(this);
}
return this.singletonInstance;
}
//使用createAopProxy放回的AopProxy來得到代理對象。
protected Object getProxy(AopProxy aopProxy) {
return aopProxy.getProxy(this.beanClassLoader);
}
ProxyFactoryBean的父類是AdvisedSupport,Spring使用AopProxy接口把AOP代理的實現(xiàn)與框架的其他部分分離開來;在AdvisedSupport中通過這樣的方式來得到AopProxy,當(dāng)然這里需要得到AopProxyFactory的幫助 - 下面我們看到Spring為我們提供的實現(xiàn),來幫助我們方便的從JDK或者cglib中得到我們想要的代理對象:
- protected synchronized AopProxy createAopProxy() {
- if (!this.isActive) {
- activate();
- }
- return getAopProxyFactory().createAopProxy(this);
- }
protected synchronized AopProxy createAopProxy() {
if (!this.isActive) {
activate();
}
return getAopProxyFactory().createAopProxy(this);
}
而在ProxyConfig中對使用的AopProxyFactory做了定義:
-
-
- private transient AopProxyFactory aopProxyFactory = new DefaultAopProxyFactory();
//這個DefaultAopProxyFactory是Spring用來生成AopProxy的地方,
//當(dāng)然了它包含JDK和Cglib兩種實現(xiàn)方式。
private transient AopProxyFactory aopProxyFactory = new DefaultAopProxyFactory();
其中在DefaultAopProxyFactory中是這樣生成AopProxy的:
- public AopProxy createAopProxy(AdvisedSupport advisedSupport) throws AopConfigException {
-
- if (advisedSupport.isOptimize() || advisedSupport.isProxyTargetClass() ||
- advisedSupport.getProxiedInterfaces().length == 0) {
-
- if (!cglibAvailable) {
- throw new AopConfigException(
- "Cannot proxy target class because CGLIB2 is not available. " +
- "Add CGLIB to the class path or specify proxy interfaces.");
- }
-
- return CglibProxyFactory.createCglibProxy(advisedSupport);
- }
- else {
-
- return new JdkDynamicAopProxy(advisedSupport);
- }
- }
public AopProxy createAopProxy(AdvisedSupport advisedSupport) throws AopConfigException {
//首先考慮使用cglib來實現(xiàn)代理對象,當(dāng)然如果同時目標(biāo)對象不是接口的實現(xiàn)類的話
if (advisedSupport.isOptimize() || advisedSupport.isProxyTargetClass() ||
advisedSupport.getProxiedInterfaces().length == 0) {
//這里判斷如果不存在cglib庫,直接拋出異常。
if (!cglibAvailable) {
throw new AopConfigException(
"Cannot proxy target class because CGLIB2 is not available. " +
"Add CGLIB to the class path or specify proxy interfaces.");
}
// 這里使用Cglib來生成Proxy,如果target不是接口的實現(xiàn)的話,返回cglib類型的AopProxy
return CglibProxyFactory.createCglibProxy(advisedSupport);
}
else {
// 這里使用JDK來生成Proxy,返回JDK類型的AopProxy
return new JdkDynamicAopProxy(advisedSupport);
}
}
于是我們就可以看到其中的代理對象可以由JDK或者Cglib來生成,我們看到JdkDynamicAopProxy類和Cglib2AopProxy都實現(xiàn)的是AopProxy的接口,在JdkDynamicAopProxy實現(xiàn)中我們可以看到Proxy是怎樣生成的:
- public Object getProxy(ClassLoader classLoader) {
- if (logger.isDebugEnabled()) {
- Class targetClass = this.advised.getTargetSource().getTargetClass();
- logger.debug("Creating JDK dynamic proxy" +
- (targetClass != null ? " for [" + targetClass.getName() + "]" : ""));
- }
- Class[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised);
- findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
-
- return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
- }
public Object getProxy(ClassLoader classLoader) {
if (logger.isDebugEnabled()) {
Class targetClass = this.advised.getTargetSource().getTargetClass();
logger.debug("Creating JDK dynamic proxy" +
(targetClass != null ? " for [" + targetClass.getName() + "]" : ""));
}
Class[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised);
findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
//這里我們調(diào)用JDK Proxy來生成需要的Proxy實例
return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
}
這樣用Proxy包裝target之后,通過ProxyFactoryBean得到對其方法的調(diào)用就被Proxy攔截了, ProxyFactoryBean的getObject()方法得到的實際上是一個Proxy了,我們的target對象已經(jīng)被封裝了。對 ProxyFactoryBean這個工廠bean而言,其生產(chǎn)出來的對象是封裝了目標(biāo)對象的代理對象。