精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

AOP那點(diǎn)事兒:面向切面編程

開發(fā) 后端
今天我要和大家分享的是 AOP(Aspect-Oriented Programming)這個東西,名字與 OOP 僅差一個字母,其實(shí)它是對 OOP 編程方式的一種補(bǔ)充,并非是取而代之。翻譯過來就是“面向方面編程”,可我更傾向于翻譯為“面向切面編程”。它聽起有些的神秘,為什么呢?當(dāng)你看完這篇文章的時候,就就知道,我們做的很重要的工作就是去寫這個“切面”。

又是一個周末,剛給寶寶喂完牛奶,終于讓她睡著了。所以現(xiàn)在我才能騰出手來,坐在電腦面前給大家寫這篇文章。

今天我要和大家分享的是 AOP(Aspect-Oriented Programming)這個東西,名字與 OOP 僅差一個字母,其實(shí)它是對 OOP 編程方式的一種補(bǔ)充,并非是取而代之。翻譯過來就是“面向方面編程”,可我更傾向于翻譯為“面向切面編程”。它聽起有些的神秘,為什么呢?當(dāng)你看完這篇文章的時候,就就知道,我們做的很重要的工作就是去寫這個“切面”。那么什么是“切面”呢?

沒錯!就是用一把刀來切一坨面。注意,相對于面而言,我們一定是橫著來切它,這簡稱為“橫切”。可以把一段代碼想象成一坨面,同樣也可以用一把刀來橫切它,下面要做的就是如何去實(shí)現(xiàn)這把刀!

需要澄清的是,這個概念不是由 Rod Johnson(老羅)提出的。其實(shí)很早以前就有了,目前最知名最強(qiáng)大的 Java 開源項目就是 AspectJ 了,然而它的前身是 AspectWerkz(該項目已經(jīng)在 2005 年停止更新),這才是 AOP 的老祖宗。老羅(一個頭發(fā)禿得和我老爸有一拼的天才)寫了一個叫做 Spring 框架,從此一炮走紅,成為了 Spring 之父。他在自己的 IOC 的基礎(chǔ)之上,又實(shí)現(xiàn)了一套 AOP 的框架,后來仿佛發(fā)現(xiàn)自己越來越走進(jìn)深淵里,在不能自拔的時候,有人建議他還是集成 AspectJ 吧,他在萬般無奈之下才接受了該建議。于是,我們現(xiàn)在用得最多的想必就是 Spring + AspectJ 這種 AOP 框架了。

那么 AOP 到底是什么?如何去使用它?本文將逐步帶您進(jìn)入 AOP 的世界,讓您感受到前所未有的暢快!

不過在開始講解 AOP 之前,我想有必要回憶一下這段代碼:

1. 寫死代碼

先來一個接口:

  1. public interface Greeting {  
  2.  
  3.     void sayHello(String name);  

還有一個實(shí)現(xiàn)類:

  1. public class GreetingImpl implements Greeting {  
  2.  
  3.     @Override 
  4.     public void sayHello(String name) {  
  5.         before();  
  6.         System.out.println("Hello! " + name);  
  7.         after();  
  8.     }  
  9.  
  10.     private void before() {  
  11.         System.out.println("Before");  
  12.     }  
  13.  
  14.     private void after() {  
  15.         System.out.println("After");  
  16.     }  

before() 與 after() 方法寫死在 sayHello() 方法體中了,這樣的代碼的味道非常不好。如果哪位仁兄大量寫了這樣的代碼,肯定要被你的架構(gòu)師罵個夠嗆。

比如:我們要統(tǒng)計每個方法的執(zhí)行時間,以對性能作出評估,那是不是要在每個方法的一頭一尾都做點(diǎn)手腳呢?

再比如:我們要寫一個 JDBC 程序,那是不是也要在方法的開頭去連接數(shù)據(jù)庫,方法的末尾去關(guān)閉數(shù)據(jù)庫連接呢?

這樣的代碼只會把程序員累死,把架構(gòu)師氣死!

一定要想辦法對上面的代碼進(jìn)行重構(gòu),首先給出三個解決方案:

2. 靜態(tài)代理

最簡單的解決方案就是使用靜態(tài)代理模式了,我們單獨(dú)為 GreetingImpl 這個類寫一個代理類:

  1. public class GreetingProxy implements Greeting {  
  2.  
  3.     private GreetingImpl greetingImpl;  
  4.  
  5.     public GreetingProxy(GreetingImpl greetingImpl) {  
  6.         this.greetingImpl = greetingImpl;  
  7.     }  
  8.  
  9.     @Override 
  10.     public void sayHello(String name) {  
  11.         before();  
  12.         greetingImpl.sayHello(name);  
  13.         after();  
  14.     }  
  15.  
  16.     private void before() {  
  17.         System.out.println("Before");  
  18.     }  
  19.  
  20.     private void after() {  
  21.         System.out.println("After");  
  22.     }  

就用這個 GreetingProxy 去代理 GreetingImpl,下面看看客戶端如何來調(diào)用:

  1. public class Client {  
  2.  
  3.     public static void main(String[] args) {  
  4.         Greeting greetingProxy = new GreetingProxy(new GreetingImpl());  
  5.         greetingProxy.sayHello("Jack");  
  6.     }  

這樣寫沒錯,但是有個問題,XxxProxy 這樣的類會越來越多,如何才能將這些代理類盡可能減少呢?最好只有一個代理類。

這是我們就需要使用 JDK 提供的動態(tài)代理了。 

3. JDK 動態(tài)代理

  1. public class JDKDynamicProxy implements InvocationHandler {  
  2.  
  3.     private Object target;  
  4.  
  5.     public JDKDynamicProxy(Object target) {  
  6.         this.target = target;  
  7.     }  
  8.  
  9.     @SuppressWarnings("unchecked")  
  10.     public <T> T getProxy() {  
  11.         return (T) Proxy.newProxyInstance(  
  12.             target.getClass().getClassLoader(),  
  13.             target.getClass().getInterfaces(),  
  14.             this 
  15.         );  
  16.     }  
  17.  
  18.     @Override 
  19.     public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {  
  20.         before();  
  21.         Object result = method.invoke(target, args);  
  22.         after();  
  23.         return result;  
  24.     }  
  25.  
  26.     private void before() {  
  27.         System.out.println("Before");  
  28.     }  
  29.  
  30.     private void after() {  
  31.         System.out.println("After");  
  32.     }  

客戶端是這樣調(diào)用的:

  1. public class Client {  
  2.  
  3.     public static void main(String[] args) {  
  4.         Greeting greeting = new JDKDynamicProxy(new GreetingImpl()).getProxy();  
  5.         greeting.sayHello("Jack");  
  6.     }  

這樣所有的代理類都合并到動態(tài)代理類中了,但這樣做仍然存在一個問題:JDK 給我們提供的動態(tài)代理只能代理接口,而不能代理沒有接口的類。有什么方法可以解決呢?

4. CGLib 動態(tài)代理

我們使用開源的 CGLib 類庫可以代理沒有接口的類,這樣就彌補(bǔ)了 JDK 的不足。CGLib 動態(tài)代理類是這樣玩的:

  1. public class CGLibDynamicProxy implements MethodInterceptor {  
  2.  
  3.     private static CGLibDynamicProxy instance = new CGLibDynamicProxy();  
  4.  
  5.     private CGLibDynamicProxy() {  
  6.     }  
  7.  
  8.     public static CGLibDynamicProxy getInstance() {  
  9.         return instance;  
  10.     }  
  11.  
  12.     @SuppressWarnings("unchecked")  
  13.     public <T> T getProxy(Class<T> cls) {  
  14.         return (T) Enhancer.create(cls, this);  
  15.     }  
  16.  
  17.     @Override 
  18.     public Object intercept(Object target, Method method, Object[] args, MethodProxy proxy) throws Throwable {  
  19.         before();  
  20.         Object result = proxy.invokeSuper(target, args);  
  21.         after();  
  22.         return result;  
  23.     }  
  24.  
  25.     private void before() {  
  26.         System.out.println("Before");  
  27.     }  
  28.  
  29.     private void after() {  
  30.         System.out.println("After");  
  31.     }  

以上代碼中了 Singleton 模式,那么客戶端調(diào)用也更加輕松了:

  1. public class Client {  
  2.  
  3.     public static void main(String[] args) {  
  4.         Greeting greeting = CGLibDynamicProxy.getInstance().getProxy(GreetingImpl.class);  
  5.         greeting.sayHello("Jack");  
  6.     }  

到此為止,我們能做的都做了,問題似乎全部都解決了。但事情總不會那么完美,而我們一定要追求完美!

老羅搞出了一個 AOP 框架,能否做到完美而優(yōu)雅呢?請大家繼續(xù)往下看吧!

#p#

5. Spring AOP:前置增強(qiáng)、后置增強(qiáng)、環(huán)繞增強(qiáng)(編程式)

在 Spring AOP 的世界里,與 AOP 相關(guān)的術(shù)語實(shí)在太多,往往也是我們的“攔路虎”,不管是看那本書或是技術(shù)文檔,在開頭都要將這些術(shù)語逐個灌輸給讀者。我想這完全是在嚇唬人了,其實(shí)沒那么復(fù)雜的,大家放輕松一點(diǎn)。

我們上面例子中提到的 before() 方法,在 Spring AOP 里就叫 Before Advice(前置增強(qiáng))。有些人將 Advice 直譯為“通知”,我想這是不太合適的,因為它根本就沒有“通知”的含義,而是對原有代碼功能的一種“增強(qiáng)”。再說,CGLib 中也有一個 Enhancer 類,它就是一個增強(qiáng)類。

此外,像 after() 這樣的方法就叫 After Advice(后置增強(qiáng)),因為它放在后面來增強(qiáng)代碼的功能

如果能把 before() 與 after() 合并在一起,那就叫 Around Advice(環(huán)繞增強(qiáng)),就像漢堡一樣,中間夾一根火腿。

這三個概念是不是輕松地理解了呢?如果是,那就繼續(xù)吧!

我們下面要做的就是去實(shí)現(xiàn)這些所謂的“增強(qiáng)類”,讓他們橫切到代碼中,而不是將這些寫死在代碼中。

先來一個前置增強(qiáng)類吧:

  1. public class GreetingBeforeAdvice implements MethodBeforeAdvice {  
  2.  
  3.     @Override 
  4.     public void before(Method method, Object[] args, Object target) throws Throwable {  
  5.         System.out.println("Before");  
  6.     }  

注意:這個類實(shí)現(xiàn)了 org.springframework.aop.MethodBeforeAdvice 接口,我們將需要增強(qiáng)的代碼放入其中。

再來一個后置增強(qiáng)類吧:

  1. public class GreetingAfterAdvice implements AfterReturningAdvice {  
  2.  
  3.     @Override 
  4.     public void afterReturning(Object result, Method method, Object[] args, Object target) throws Throwable {  
  5.         System.out.println("After");  
  6.     }  

類似地,這個類實(shí)現(xiàn)了 org.springframework.aop.AfterReturningAdvice 接口。

最后用一個客戶端來把它們集成起來,看看如何調(diào)用吧:

  1. public class Client {  
  2.  
  3.     public static void main(String[] args) {  
  4.         ProxyFactory proxyFactory = new ProxyFactory();     // 創(chuàng)建代理工廠  
  5.         proxyFactory.setTarget(new GreetingImpl());         // 射入目標(biāo)類對象  
  6.         proxyFactory.addAdvice(new GreetingBeforeAdvice()); // 添加前置增強(qiáng)  
  7.         proxyFactory.addAdvice(new GreetingAfterAdvice());  // 添加后置增強(qiáng)   
  8.  
  9.         Greeting greeting = (Greeting) proxyFactory.getProxy(); // 從代理工廠中獲取代理  
  10.         greeting.sayHello("Jack");                              // 調(diào)用代理的方法  
  11.     }  

請仔細(xì)閱讀以上代碼及其注釋,您會發(fā)現(xiàn),其實(shí) Spring AOP 還是挺簡單的,對嗎?

當(dāng)然,我們完全可以只定義一個增強(qiáng)類,讓它同時實(shí)現(xiàn) MethodBeforeAdvice 與 AfterReturningAdvice 這兩個接口,如下:

  1. public class GreetingBeforeAndAfterAdvice implements MethodBeforeAdvice, AfterReturningAdvice {  
  2.  
  3.     @Override 
  4.     public void before(Method method, Object[] args, Object target) throws Throwable {  
  5.         System.out.println("Before");  
  6.     }  
  7.  
  8.     @Override 
  9.     public void afterReturning(Object result, Method method, Object[] args, Object target) throws Throwable {  
  10.         System.out.println("After");  
  11.     }  

這樣我們只需要使用一行代碼,同時就可以添加前置與后置增強(qiáng):

  1. proxyFactory.addAdvice(new GreetingBeforeAndAfterAdvice()); 

剛才有提到“環(huán)繞增強(qiáng)”,其實(shí)這個東西可以把“前置增強(qiáng)”與“后置增強(qiáng)”的功能給合并起來,無需讓我們同時實(shí)現(xiàn)以上兩個接口。

  1. public class GreetingAroundAdvice implements MethodInterceptor {  
  2.  
  3.     @Override 
  4.     public Object invoke(MethodInvocation invocation) throws Throwable {  
  5.         before();  
  6.         Object result = invocation.proceed();  
  7.         after();  
  8.         return result;  
  9.     }  
  10.  
  11.     private void before() {  
  12.         System.out.println("Before");  
  13.     }  
  14.  
  15.     private void after() {  
  16.         System.out.println("After");  
  17.     }  

環(huán)繞增強(qiáng)類需要實(shí)現(xiàn) org.aopalliance.intercept.MethodInterceptor 接口。注意,這個接口不是 Spring 提供的,它是 AOP 聯(lián)盟(一個很牛逼的聯(lián)盟)寫的,Spring 只是借用了它。

在客戶端中同樣也需要將該增強(qiáng)類的對象添加到代理工廠中:

  1. proxyFactory.addAdvice(new GreetingAroundAdvice()); 

好了,這就是 Spring AOP 的基本用法,但這只是“編程式”而已。Spring AOP 如果只是這樣,那就太傻逼了,它曾經(jīng)也是一度宣傳用 Spring 配置文件的方式來定義 Bean 對象,把代碼中的 new 操作全部解脫出來。

6.   Spring AOP:前置增強(qiáng)、后置增強(qiáng)、環(huán)繞增強(qiáng)(聲明式)

先看 Spring 配置文件是如何寫的吧:

  1. <?xml version="1.0" encoding="UTF-8"?> 
  2. <beans xmlns="http://www.springframework.org/schema/beans" 
  3.        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
  4.        xmlns:context="http://www.springframework.org/schema/context" 
  5.        xsi:schemaLocation="http://www.springframework.org/schema/beans  
  6.        http://www.springframework.org/schema/beans/spring-beans.xsd  
  7.        http://www.springframework.org/schema/context  
  8.        http://www.springframework.org/schema/context/spring-context.xsd"> 
  9.  
  10.     <!-- 掃描指定包(將 @Component 注解的類自動定義為 Spring Bean) --> 
  11.     <context:component-scan base-package="aop.demo"/> 
  12.  
  13.     <!-- 配置一個代理 --> 
  14.     <bean id="greetingProxy" class="org.springframework.aop.framework.ProxyFactoryBean"> 
  15.         <property name="interfaces" value="aop.Greeting"/> <!-- 需要代理的接口 --> 
  16.         <property name="target" ref="greetingImpl"/>       <!-- 接口實(shí)現(xiàn)類 --> 
  17.         <property name="interceptorNames">                 <!-- 攔截器名稱(也就是增強(qiáng)類名稱,Spring Bean 的 id) --> 
  18.             <list> 
  19.                 <value>greetingAroundAdvice</value> 
  20.             </list> 
  21.         </property> 
  22.     </bean> 
  23.  
  24. </beans> 

一定要閱讀以上代碼的注釋,其實(shí)使用 ProxyFactoryBean 就可以取代前面的 ProxyFactory,其實(shí)它們倆就一回事兒。我認(rèn)為 interceptorNames 應(yīng)該改名為 adviceNames 或許會更容易讓人理解,不就是往這個屬性里面添加增強(qiáng)類嗎?

此外,如果只有一個增強(qiáng)類,可以使用以下方法來簡化:

  1. ...  
  2.  
  3.     <bean id="greetingProxy" class="org.springframework.aop.framework.ProxyFactoryBean"> 
  4.         <property name="interfaces" value="aop.Greeting"/> 
  5.         <property name="target" ref="greetingImpl"/> 
  6.         <property name="interceptorNames" value="greetingAroundAdvice"/> <!-- 注意這行配置 --> 
  7.     </bean> 
  8.  
  9. ... 

還需要注意的是,這里使用了 Spring 2.5+ 的特性“Bean 掃描”,這樣我們就無需在 Spring 配置文件里不斷地定義 <bean id="xxx" class="xxx"/> 了,從而解脫了我們的雙手。

看看這是有多么的簡單:

  1. @Component 
  2. public class GreetingImpl implements Greeting {  
  3.  
  4.     ...  
  1. @Component 
  2. public class GreetingAroundAdvice implements MethodInterceptor {  
  3.  
  4.     ...  

最后看看客戶端吧:

  1. public class Client {  
  2.  
  3.     public static void main(String[] args) {  
  4.         ApplicationContext context = new ClassPathXmlApplicationContext("aop/demo/spring.xml"); // 獲取 Spring Context  
  5.         Greeting greeting = (Greeting) context.getBean("greetingProxy");                        // 從 Context 中根據(jù) id 獲取 Bean 對象(其實(shí)就是一個代理)  
  6.         greeting.sayHello("Jack");                                                              // 調(diào)用代理的方法  
  7.     }  

代碼量確實(shí)少了,我們將配置性的代碼放入配置文件,這樣也有助于后期維護(hù)。更重要的是,代碼只關(guān)注于業(yè)務(wù)邏輯,而將配置放入文件中。這是一條最佳實(shí)踐!

除了上面提到的那三類增強(qiáng)以外,其實(shí)還有兩類增強(qiáng)也需要了解一下,關(guān)鍵的時候您要能想得到它們才行。 

#p#

7. Spring AOP:拋出增強(qiáng)

程序報錯,拋出異常了,一般的做法是打印到控制臺或日志文件中,這樣很多地方都得去處理,有沒有一個一勞永逸的方法呢?那就是 Throws Advice(拋出增強(qiáng)),它確實(shí)很強(qiáng),不信你就繼續(xù)往下看:

  1. @Component 
  2. public class GreetingImpl implements Greeting {  
  3.  
  4.     @Override 
  5.     public void sayHello(String name) {  
  6.         System.out.println("Hello! " + name);  
  7.  
  8.         throw new RuntimeException("Error"); // 故意拋出一個異常,看看異常信息能否被攔截到  
  9.     }  

下面是拋出增強(qiáng)類的代碼:

  1. @Component 
  2. public class GreetingThrowAdvice implements ThrowsAdvice {  
  3.  
  4.     public void afterThrowing(Method method, Object[] args, Object target, Exception e) {  
  5.         System.out.println("---------- Throw Exception ----------");  
  6.         System.out.println("Target Class: " + target.getClass().getName());  
  7.         System.out.println("Method Name: " + method.getName());  
  8.         System.out.println("Exception Message: " + e.getMessage());  
  9.         System.out.println("-------------------------------------");  
  10.     }  

拋出增強(qiáng)類需要實(shí)現(xiàn) org.springframework.aop.ThrowsAdvice 接口,在接口方法中可獲取方法、參數(shù)、目標(biāo)對象、異常對象等信息。我們可以把這些信息統(tǒng)一寫入到日志中,當(dāng)然也可以持久化到數(shù)據(jù)庫中。

這個功能確實(shí)太棒了!但還有一個更厲害的增強(qiáng)。如果某個類實(shí)現(xiàn)了 A 接口,但沒有實(shí)現(xiàn) B 接口,那么該類可以調(diào)用 B 接口的方法嗎?如果您沒有看到下面的內(nèi)容,一定不敢相信原來這是可行的!

8. Spring AOP:引入增強(qiáng)

以上提到的都是對方法的增強(qiáng),那能否對類進(jìn)行增強(qiáng)呢?用 AOP 的行話來講,對方法的增強(qiáng)叫做 Weaving(織入),而對類的增強(qiáng)叫做 Introduction(引入)。而 Introduction Advice(引入增強(qiáng))就是對類的功能增強(qiáng),它也是 Spring AOP 提供的最后一種增強(qiáng)。建議您一開始千萬不要去看《Spring Reference》,否則您一定會后悔的。因為當(dāng)您看了以下的代碼示例后,一定會徹底明白什么才是引入增強(qiáng)。

定義了一個新接口 Apology(道歉):

  1. public interface Apology {  
  2.  
  3.     void saySorry(String name);  

但我不想在代碼中讓 GreetingImpl 直接去實(shí)現(xiàn)這個接口,我想在程序運(yùn)行的時候動態(tài)地實(shí)現(xiàn)它。因為加入我實(shí)現(xiàn)了這個接口,那么我就一定要改寫 GreetingImpl 這個類,關(guān)鍵是我不想改它,或許在真實(shí)場景中,這個類有1萬行代碼,我實(shí)在是不敢動了。于是,我需要借助 Spring 的引入增強(qiáng)。這個有點(diǎn)意思了!

  1. @Component 
  2. public class GreetingIntroAdvice extends DelegatingIntroductionInterceptor implements Apology {  
  3.  
  4. &nbsp; &nbsp; @Override 
  5. &nbsp; &nbsp; public Object invoke(MethodInvocation invocation) throws Throwable {  
  6. &nbsp; &nbsp; &nbsp; &nbsp; return super.invoke(invocation);  
  7. &nbsp; &nbsp; }  
  8.  
  9.     @Override 
  10.     public void saySorry(String name) {  
  11.         System.out.println("Sorry! " + name);  
  12.     }  

以上定義了一個引入增強(qiáng)類,擴(kuò)展了 org.springframework.aop.support.DelegatingIntroductionInterceptor 類,同時也實(shí)現(xiàn)了新定義的 Apology 接口。在類中首先覆蓋了父類的 invoke() 方法,然后實(shí)現(xiàn)了 Apology 接口的方法。我就是想用這個增強(qiáng)類去豐富 GreetingImpl 類的功能,那么這個 GreetingImpl 類無需直接實(shí)現(xiàn) Apology 接口,就可以在程序運(yùn)行的時候調(diào)用 Apology 接口的方法了。這簡直是太神奇的!

看看是如何配置的吧:

  1. <?xml version="1.0" encoding="UTF-8"?> 
  2. <beans xmlns="http://www.springframework.org/schema/beans" 
  3.        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
  4.        xmlns:context="http://www.springframework.org/schema/context" 
  5.        xsi:schemaLocation="http://www.springframework.org/schema/beans  
  6.        http://www.springframework.org/schema/beans/spring-beans.xsd  
  7.        http://www.springframework.org/schema/context  
  8.        http://www.springframework.org/schema/context/spring-context.xsd"> 
  9.  
  10.     <context:component-scan base-package="aop.demo"/> 
  11.  
  12.     <bean id="greetingProxy" class="org.springframework.aop.framework.ProxyFactoryBean"> 
  13.         <property name="interfaces" value="aop.demo.Apology"/>          <!-- 需要動態(tài)實(shí)現(xiàn)的接口 --> 
  14.         <property name="target" ref="greetingImpl"/>                    <!-- 目標(biāo)類 --> 
  15.         <property name="interceptorNames" value="greetingIntroAdvice"/> <!-- 引入增強(qiáng) --> 
  16.         <property name="proxyTargetClass" value="true"/>                <!-- 代理目標(biāo)類(默認(rèn)為 false,代理接口) --> 
  17.     </bean> 
  18.  
  19. </beans> 

需要注意 proxyTargetClass 屬性,它表明是否代理目標(biāo)類,默認(rèn)為 false,也就是代理接口了,此時 Spring 就用 JDK 動態(tài)代理。如果為 false,那么 Spring 就用 CGLib 動態(tài)代理。這簡直就是太方便了!Spring 封裝了這一切,讓程序員不在關(guān)心那么多的細(xì)節(jié)。我們要向老羅同志致敬,您是我們心中永遠(yuǎn)的 idol!

當(dāng)您看完下面的客戶端代碼,一定會完全明白以上的這一切:

  1. public class Client {  
  2.  
  3.     public static void main(String[] args) {  
  4.         ApplicationContext context = new ClassPathXmlApplicationContext("aop/demo/spring.xml");  
  5.         GreetingImpl greetingImpl = (GreetingImpl) context.getBean("greetingProxy"); // 注意:轉(zhuǎn)型為目標(biāo)類,而并非它的 Greeting 接口  
  6.         greetingImpl.sayHello("Jack");  
  7.  
  8.         Apology apology = (Apology) greetingImpl; // 將目標(biāo)類強(qiáng)制向上轉(zhuǎn)型為 Apology 接口(這是引入增強(qiáng)給我們帶來的特性,也就是“接口動態(tài)實(shí)現(xiàn)”功能)  
  9.         apology.saySorry("Jack");  
  10.     }  

沒想到 saySorry() 方法原來是可以被 greetingImpl 對象來直接調(diào)用的,只需將其強(qiáng)制轉(zhuǎn)換為該接口即可。

我們再次感謝 Spring AOP,感謝老羅給我們提供了這么強(qiáng)大的特性!

其實(shí),Spring AOP 還有很多精彩的地方,下一篇將介紹更多更有價值的 AOP 技術(shù),讓大家得到更多的收獲。

原文鏈接:http://my.oschina.net/huangyong/blog/161338

責(zé)任編輯:林師授 來源: 黃勇的博客
相關(guān)推薦

2012-02-10 10:32:33

JavaSpring

2009-08-24 09:46:40

面向切面編程AOP

2022-05-26 15:30:21

Spring AOP框架

2023-11-07 16:00:25

面向切面編程開發(fā)

2022-05-26 09:03:39

AOP編程

2023-10-20 09:32:25

Java技術(shù)

2011-04-26 09:33:04

SpringAOP

2024-05-21 09:55:43

AspectOrientedAOP

2013-12-26 13:35:39

2020-01-03 07:57:39

UDPTCP網(wǎng)絡(luò)協(xié)議

2017-09-12 08:03:29

數(shù)據(jù)庫MySQL主庫

2015-12-08 14:49:13

SDN軟件定義網(wǎng)絡(luò)

2011-12-26 11:13:24

密碼

2023-11-30 08:00:54

面向?qū)ο?/a>面向切面

2018-03-30 16:03:04

軟件無狀態(tài)”

2023-12-04 11:02:53

C++空類

2024-04-10 08:59:39

SpringAOP業(yè)務(wù)

2012-03-12 21:23:47

Windows pho

2021-04-13 09:12:45

網(wǎng)絡(luò)設(shè)備無線路由器交換機(jī)

2010-04-26 08:53:06

面向方面編程.NET
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號

国产一区二区三区日韩精品 | 久久精品中文字幕一区二区三区 | 日韩av激情| eeuss鲁片一区二区三区在线观看| 青青久久av北条麻妃海外网| 欧美色图校园春色| 97人人爽人人澡人人精品| 国产亚洲精品资源在线26u| 91精品国产综合久久香蕉的用户体验| 久久精品www人人爽人人| 中文字幕亚洲影视| 欧美性猛交xxxx乱大交3| 俄罗斯精品一区二区| 青青草原免费观看| 亚洲欧美日本国产| 亚洲高清一区二区三区| 日韩欧美一区二区在线观看| 免费看日韩av| 欧美一级视频| 在线电影av不卡网址| 欧美激情 亚洲| 狂野欧美性猛交xxxx| 福利视频导航一区| 国产一区二区片| 日本三级在线播放完整版| 久久亚洲一区二区三区明星换脸 | 国产精品无av码在线观看| 女人被男人躁得好爽免费视频| 日本午夜在线| 国产成人鲁色资源国产91色综| 久久成人在线视频| 午夜在线观看一区| 久久婷婷国产| 色菇凉天天综合网| 亚洲日本欧美在线| 青青九九免费视频在线| 成人精品国产免费网站| 91色p视频在线| 日本熟妇成熟毛茸茸| 亚洲高清影视| 中文字幕亚洲无线码在线一区| 艳妇乳肉亭妇荡乳av| 6080亚洲理论片在线观看| 欧美午夜精品久久久久久浪潮| 日韩欧美猛交xxxxx无码| 伦xxxx在线| 亚洲婷婷在线视频| 久久久久久久久黄色| 在线观看免费黄色小视频| 日韩一级毛片| 亚洲午夜久久久久久久| 成年人网站av| 未满十八勿进黄网站一区不卡| 亚洲曰韩产成在线| 视频一区视频二区视频三区高| 国产乱叫456在线| 精品一区二区三区不卡 | 亚洲午夜天堂| 亚洲三级小视频| 综合一区中文字幕| 青青草在线播放| 国产综合色在线| 亚洲精品女av网站| 性一交一乱一精一晶| 日韩av成人高清| 国产精品爽爽爽| 国产亚洲成av人片在线观黄桃| 久久综合五月婷婷| 在线观看视频91| 毛葺葺老太做受视频| 国精产品一区二区三区有限公司| 欧美怡红院视频| 亚洲美女性囗交| 波多视频一区| 91久久香蕉国产日韩欧美9色| 超碰网在线观看| 日韩免费小视频| 欧美精品日韩综合在线| 亚洲三级在线视频| av激情成人网| 欧美日高清视频| 国产一级不卡毛片| 国产精品xnxxcom| 亚洲国产精品成人一区二区| 中文字幕国产专区| 国产精品久久久久久久久妇女 | av网站大全在线观看| 成人av在线播放网站| 国产原创精品| 亚洲第一精品网站| 国产成人综合自拍| 亚洲伊人第一页| 亚洲av成人精品一区二区三区在线播放| 精品一区中文字幕| 国产日韩欧美精品| 成人p站proumb入口| 国产性做久久久久久| 欧美精品久久96人妻无码| 国产调教在线| 欧美肥妇毛茸茸| 可以直接看的无码av| 欧美日韩一本| 久久精品中文字幕免费mv| 日本一级黄色大片| 久久99久久99| 欧美精品亚洲精品| 人妖欧美1区| 欧美色窝79yyyycom| 中文字幕无人区二| 六十路息与子猛烈交尾| 一级毛片精品毛片| 国产亚洲精品久久久优势| 久久久精品国产sm调教网站| 999福利视频| 四虎在线精品| 日本道色综合久久| 香蕉视频xxx| 国内精品免费| 亚洲激情在线观看| 国产精品视频一区二区三 | 日本一区二区视频在线观看| 亚洲视频电影| 性欧美1819sex性高清| 欧美日精品一区视频| jjzzjjzz欧美69巨大| 亚洲人成网77777色在线播放| 亚洲欧美综合另类中字| 国产极品美女高潮无套嗷嗷叫酒店| 久久国产福利国产秒拍| 欧美一区二区三区四区夜夜大片| 欧美13一16娇小xxxx| 一本大道综合伊人精品热热| 给我免费观看片在线电影的| 很黄很黄激情成人| 国产精品99久久99久久久二8| 后进极品白嫩翘臀在线视频| 亚洲精品乱码久久久久久黑人| 久久撸在线视频| 日韩高清在线观看一区二区| 日韩中文字幕国产精品| 好吊操这里只有精品| 粉嫩av一区二区三区| 日韩一区二区高清视频| 成人国产精品入口免费视频| 亚洲人成在线观| 日韩中文字幕高清| 国产激情一区二区三区| 一区二区三区免费看| crdy在线观看欧美| 久久精品国产2020观看福利| 国产一区二区三区四区视频| 9色porny自拍视频一区二区| 亚洲午夜高清视频| 欧美日韩破处视频| 亚洲日韩中文字幕| 中文字幕日本视频| 国产精品久久国产精麻豆99网站| 国产成a人亚洲精v品在线观看| 亚洲综合色婷婷在线观看| 一区二区三区www| 中文字幕在线播放日韩| 中文字幕在线观看一区| 熟妇女人妻丰满少妇中文字幕| 国产成人一区二区三区影院| 久久91亚洲精品中文字幕| 亚洲国产综合网| 椎名由奈av一区二区三区| 91欧美一区二区三区| 波多野结衣在线观看一区二区三区 | 精品国产一区二区国模嫣然| 97久久久久久久| 国产欧美精品在线观看| 97超碰青青草| 精品无人区麻豆乱码久久久| 97超视频免费观看| 亚洲AV无码国产精品午夜字幕| 国产欧美日韩精品一区| 天天久久综合网| 99国产成+人+综合+亚洲欧美| 亚洲最大av网站| 华人av在线| 亚洲精品suv精品一区二区| 奇米影视第四色777| 中文乱码免费一区二区| 一级黄色香蕉视频| 欧美在线精品一区| 51国产成人精品午夜福中文下载 | 国产伊人精品在线| 波多野结衣中文字幕久久| 在线综合亚洲欧美在线视频| 九一在线免费观看| 日本中文在线一区| 日本一区二区三区视频在线观看 | 丰乳肥臀在线| 欧美成人在线直播| 日日夜夜操视频| 夜夜爽夜夜爽精品视频| 男女做爰猛烈刺激| 久久久噜噜噜| av片在线免费| 99久久夜色精品国产亚洲96| 成人疯狂猛交xxx| 午夜影院在线播放| 不卡av日日日| 99视频在线观看地址| 精品av综合导航| 国产一区二区在线不卡| 欧美性猛交xxxx久久久| 久久精品第一页| 亚洲欧美综合在线精品| 插吧插吧综合网| 日本中文在线一区| 国产视频九色蝌蚪| 精品免费av| 精品久久久久久乱码天堂| 国产精品视频首页| 国产精品久久久久一区二区| 性国裸体高清亚洲| 色狠狠av一区二区三区香蕉蜜桃| 国产毛片毛片毛片毛片| 亚洲无线码一区二区三区| 萌白酱视频在线| 国产成人综合网| 亚洲美免无码中文字幕在线 | 91九色蝌蚪91por成人| 色诱亚洲精品久久久久久| 日韩乱码在线观看| 亚洲香肠在线观看| 岛国毛片在线观看| 亚洲色图欧美在线| 久久精品女同亚洲女同13| 国产一区二区毛片| 久久成人福利视频| 九色精品国产蝌蚪| 91欧美激情另类亚洲| 日本久久久久| 91精品国产乱码久久久久久久久| 好男人免费精品视频| 欧美一区二区观看视频| 91麻豆国产视频| 天天影视网天天综合色在线播放| 麻豆一区产品精品蜜桃的特点| 久久日韩精品一区二区五区| 亚洲一区二区乱码| 国产精品一区二区三区99| 91精产国品一二三产区别沈先生| 一本一本久久| 男同互操gay射视频在线看| 欧美电影免费| 91社在线播放| 国产精品videosex极品| 国产精品一线二线三线| 欧美高清在线| 欧美福利精品| 国产欧美日韩精品一区二区免费 | 色呦呦国产精品| 中文字幕在线观看视频免费| 欧美影视一区在线| 97视频免费在线| 欧美一区二区三区免费大片| 国产精品乱码一区二区视频| 亚洲欧美偷拍另类a∨色屁股| 搜索黄色一级片| 亚洲综合自拍偷拍| 成人免费a视频| 欧洲国产伦久久久久久久| 国产精品999在线观看| 亚洲女女做受ⅹxx高潮| 欧美激情 一区| 自拍偷拍国产亚洲| 亚洲人做受高潮| 亚洲午夜免费视频| 极品盗摄国产盗摄合集| 午夜电影一区二区| 国产无套在线观看| 色偷偷久久人人79超碰人人澡| 中文字幕一区二区人妻| 欧美一级精品在线| 国产欧美日韩综合精品一区二区三区| 日韩视频在线永久播放| 国产精品无码在线播放| 欧美日韩精品一区二区在线播放| 国产www视频| 日韩午夜在线观看视频| 日韩av视屏| 亚洲美女视频网站| 三级做a全过程在线观看| 丝袜美腿精品国产二区| 欧美精品videossex少妇| 美女视频久久黄| av网站免费在线观看| 久久九九国产精品怡红院| 香蕉视频国产在线观看| 色视频www在线播放国产成人| 精品日韩av| 91国内免费在线视频| 本网站久久精品| 精品国产91亚洲一区二区三区www 精品国产_亚洲人成在线 | av不卡中文字幕| 久久久一区二区三区捆绑**| 精品欧美一区二区久久久久| 一本色道久久综合亚洲91| 午夜精品久久久久久久99热黄桃 | 亚洲国产欧美视频| 91麻豆国产精品久久| 日韩高清dvd碟片| 亚洲最新在线观看| 在线免费观看毛片| 欧美日韩激情视频| 亚洲大尺度在线观看| 亚洲国产黄色片| 免费毛片在线| 欧美精品videofree1080p| 美女高潮在线观看| 91香蕉国产在线观看| 成人羞羞动漫| 浴室偷拍美女洗澡456在线| 日韩精品国产精品| 一起草在线视频| 一区二区三区av电影 | 精品国精品国产尤物美女| 永久免费av片在线观看全网站| 精品久久久91| 成人影音在线| 亚洲最大的网站| 综合国产在线| www.51色.com| 中文字幕五月欧美| 一级黄色小视频| 精品欧美乱码久久久久久| 青青国产在线| 美女视频黄免费的亚洲男人天堂| 国产亚洲欧美日韩精品一区二区三区 | 6080国产精品| thepron国产精品| 精品无码人妻一区二区三区品| 欧美日韩在线免费观看| 亚洲一区在线观| 在线观看91久久久久久| 免费污视频在线| 国产精品96久久久久久| 久操国产精品| 国产免费视频传媒| 成人夜色视频网站在线观看| 欧美成人三级在线观看| 日韩亚洲欧美一区| 国产99re66在线视频| 好吊色欧美一区二区三区 | 污污网站在线观看视频| 成人小视频免费观看| 国产一级视频在线| 亚洲成人av资源网| 黄色网页网址在线免费| 国产又爽又黄的激情精品视频| 爽爽窝窝午夜精品一区二区| 成人在线免费观看av| 国产精品一区二区无线| 亚洲色图第四色| 欧美嫩在线观看| 26uuu亚洲电影在线观看| 国产精品对白一区二区三区| 亚洲巨乳在线| 亚洲自拍偷拍图| 欧美日本韩国一区二区三区视频| 手机看片福利在线观看| 欧美成人午夜影院| 国产精品久久久久av蜜臀| 欧美成人一区二区在线观看| 国产人久久人人人人爽| 一区二区久久精品66国产精品| 欧美成人精品xxx| 日本亚洲不卡| 久久人人爽av| 亚洲国产高清不卡| a级片在线免费看| www.亚洲人.com| 成人黄色图片网站| 欧美久久综合性欧美| 国产美女一区| 亚洲毛片亚洲毛片亚洲毛片| 91麻豆精品91久久久久久清纯 | 香港欧美日韩三级黄色一级电影网站| 中文字幕人妻无码系列第三区| 精品久久久久久久中文字幕| 色呦呦视频在线| 国产精品视频一区二区高潮| 国产欧美一区| 一本色道无码道dvd在线观看| www激情久久| 色婷婷av国产精品| 日韩中文字幕网| 欧美一区在线观看视频| 欧洲精品视频在线| 91麻豆国产在线观看| 99久久精品国产一区二区成人| 久久深夜福利免费观看| 人人网欧美视频| 青青草原播放器| 亚洲国产另类av| 亚洲人成色777777精品音频|