剛開始學習到Spring AOP的時候,看那些神馬連接點,切面,通知之類的概念,完全理解不了,一頭霧水。後來照著書敲代碼上去運行,成功以後,仔細看看代碼,稍作琢磨,再看看那些概念的描述,恍然大悟,哇哦,原來是這樣,其實是那麼簡單。
所以,感覺很多知識不懂的時候,覺得那個東西特別難特別牛逼,當你明白了以後,發現原來也沒神馬大不了的。
我覺得學習這些東西先從簡單的應用例子開始,然後再慢慢的體會理論上的東西才是正確的方法。
所以,要學懂Spring 的AOP,我們也從簡單的例子開始吧。下面是一個簡單的環繞型Advice的例子。
情景:我們要調用某個商務邏輯類的某個方法,並且需要在調用方法之前做一些其他處理,比如打個日誌之類的,然後調用商務邏輯方法,調用結束後我們又想做一些其他事情,比如還是打一條日誌。這樣我們就可以用注入環繞型通知的方式來完成了,這一點和Struts2的攔截器非常相似,幾乎一樣。
1、建立商務邏輯介面
package leon.springaop.iface;public interface UserDao {public String getUserList();}
2、商務邏輯介面實作類別,也就是真實的商務邏輯類
package leon.springaop.impl;import leon.springaop.iface.UserDao;public class UserDaoImpl implements UserDao {@Overridepublic void getUserList() {System.out.println("UserDaoImpl-getUserList()...");System.out.println("get User List form database...");}}
3、環繞型通知(調用方法之前和之後要做的事情在這裡定義)
package leon.springaop.advice;import org.aopalliance.intercept.MethodInterceptor;import org.aopalliance.intercept.MethodInvocation;//Around攔截器實現MethodInterceptor介面public class AroundInterceptor implements MethodInterceptor {// 實現MethodInterceptor介面必須實現invoke方法public Object invoke(MethodInvocation invocation) throws Throwable {System.out.println("Before business logic...");Object rval = invocation.proceed();System.out.println("After business logic...");return rval;}}
4、Spring的bean設定檔,比如 springaop.xml
主要配置三個東西:
(1) 將真實業務實作類別配置成為bean
(2) 將Advice類配置成為 bean
(3) 配置真實商務邏輯代理
<?xml version="1.0" encoding="utf-8"?><!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd"> <beans><bean id="userDao" class="leon.springaop.impl.UserDaoImpl" /><bean id="myAroundInterceptor" class="leon.springaop.advice.AroundInterceptor" /><bean id="userProxy" class="org.springframework.aop.framework.ProxyFactoryBean"><property name="proxyInterfaces" value="leon.springaop.iface.UserDao"/><property name="target" ref="userDao" /><property name="interceptorNames"><list><value>myAroundInterceptor</value></list></property></bean></beans>
說明:商務邏輯代理,使用了org.springframework.aop.framework.ProxyFactoryBean,這是個代理工廠bean,該bean主要注入3個變數proxyInterfaces, target, interceptorNames,其中interceptorNames是攔截器,也是通知,屬List類型,可以注入多個攔截器,也就是添加多個value,這樣就會按先後順序進行層層遞迴攔截。
5、調用測試
package leon.springaop.test;import leon.springaop.iface.UserDao;import org.springframework.beans.factory.BeanFactory;import org.springframework.beans.factory.xml.XmlBeanFactory;import org.springframework.core.io.ClassPathResource;import org.springframework.core.io.Resource;public class TestAround {public static void main(String[] args) {Resource rsc = new ClassPathResource("springaop.xml"); //這種方式springaop.xml儲存在工程源檔案目錄下BeanFactory bf = new XmlBeanFactory(rsc);UserDao userProxy = (UserDao)bf.getBean("userProxy");userProxy.getUserList();//proxy invoke the business logic}}
運行這個類:
Before business logic...
UserDaoImpl-getUserList()...
get User List form database
After business logic...
OK,效果出來了。
現在你可以翻開書,或者其他資料去看看那些連接點,切點,切面等概念了,很容易的。
另外,Advice除了上面的環繞型通知,還有前置型、後置型、拋異常,共4種。
每種Advice的定義都是要整合相應的類或者實現相應的介面。
比如上面的環繞型Advice實現了MethodInterceptor介面。