織入(Weaving): 組裝方面來創(chuàng)建一個被通知對象。這可以在編譯時完成(例如使用AspectJ編譯器),也可以在運(yùn)行時完成。Spring和其他純Java AOP框架一樣,在運(yùn)行時完成織入。
Spring AOP組件
下面這種類圖列出了Spring中主要的AOP組件
如何使用Spring AOP
可以通過配置文件或者編程的方式來使用Spring AOP。
配置可以通過xml文件來進(jìn)行,大概有四種方式:
1. ? ? ? ?配置ProxyFactoryBean,顯式地設(shè)置advisors, advice, target等
2.????????配置AutoProxyCreator,這種方式下,還是如以前一樣使用定義的bean,但是從容器中獲得的其實(shí)已經(jīng)是代理對象
3.????????通過來配置
4.????????通過來配置,使用AspectJ的注解來標(biāo)識通知及切入點(diǎn)
也可以直接使用ProxyFactory來以編程的方式使用Spring AOP,通過ProxyFactory提供的方法可以設(shè)置target對象, advisor等相關(guān)配置,最終通過 getProxy()方法來獲取代理對象
具體使用的示例可以google. 這里略去
Spring AOP代理對象的生成
Spring提供了兩種方式來生成代理對象: JDKProxy和Cglib,具體使用哪種方式生成由AopProxyFactory根據(jù)AdvisedSupport對象的配置來決定。默認(rèn)的策略是如果目標(biāo)類是接口,則使用JDK動態(tài)代理技術(shù),否則使用Cglib來生成代理。下面我們來研究一下Spring如何使用JDK來生成代理對象,具體的生成代碼放在JdkDynamicAopProxy這個類中,直接上相關(guān)代碼:
/*
- 獲取代理類要實(shí)現(xiàn)的接口,除了Advised對象中配置的,還會加上SpringProxy,?Advised(opaque=false)?
- 檢查上面得到的接口中有沒有定義?equals或者h(yuǎn)ashcode的接口?
- 調(diào)用Proxy.newProxyInstance創(chuàng)建代理對象?
*/??
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);??
findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);??
return?Proxy.newProxyInstance(classLoader,?proxiedInterfaces,?this);??
} ?
下面的問題是,代理對象生成了,那切面是如何織入的?
我們知道InvocationHandler是JDK動態(tài)代理的核心,生成的代理對象的方法調(diào)用都會委托到InvocationHandler.invoke()方法。而通過JdkDynamicAopProxy的簽名我們可以看到這個類其實(shí)也實(shí)現(xiàn)了InvocationHandler,下面我們就通過分析這個類中實(shí)現(xiàn)的invoke()方法來具體看下Spring AOP是如何織入切面的。
publicObject?invoke(Object?proxy,?Method?method,?Object[]?args)?throwsThrowable?{??
MethodInvocation?invocation?=?null;??
Object?oldProxy?=?null;??
boolean?setProxyContext?=?false; ?
TargetSource?targetSource?=?this.advised.targetSource;??
Class?targetClass?=?null;??
Object?target?=?null; ?
try?{??
//eqauls()方法,具目標(biāo)對象未實(shí)現(xiàn)此方法??
評論
查看更多