AOP有它自己專用的常用術語:切面、切點、通知(暫且就先知道這麼多吧,後面的基於POJO的AOP中重點需要知道這3中術語的定義)。其實,任何技術都是玩了完成某一項(或者幾項)特定的工作。
通知定義了切面的工作,通知還定義了切面應該在何時進行工作,它是應該在某個方法執行之前進行工作、還是某個方法執行之後進行工作、亦或是某個方法拋出異常了進行工作等等。Spring切面定義了5種通知。
before:前置通知,在某個方法執行之前,先執行通知中定義的方法。
after:後置通知,在某個方法開始執行之後,執行通知中定義的方法(這裏倒是有點異步的感覺)。
after-returning:返回後通知,在某個方法執行,等待到方法執行完畢得到返回值,才執行通知中定義的方法。
after-throwing:拋出異常通知,在某個方法執行時拋出異常,執行通知中定義的方法。
around:環繞通知,在某個方法執行前,先執行通知中定義的方法,並且,在這個方法開始執行之後,再次執行通知中定義的方法。
切點定義了切面的工作地點,其實就是監聽哪些方法被調用,只要這些方法被調用,就啓用通知。
切面是通知和切點的結合。
基於POJO的切面
這恐怕是Spring提供的最簡單的切面使用方式了(其實面向切面的思想體現在很多地方FIilter、Inteceptor、Listener,但是Filter和Interceptor主要使用在對URL的處理上,而Listener主要使用在對事件的監聽上)。這裏有這麼一個例子,在演員進行節目表演之前,需要有主持人對節目進行描述,演員表演完畢之後,主持人要詢問下觀衆對節目的感覺。好了,主持人已經做爲一個切面被提取出來了,而後只要是演員表演,主持人就在表演前和表演後做兩件事:介紹節目和詢問觀衆。
public class Host {
/**
* 節目清單
*/
private List<String> programeList;
/**
* 記錄節目是否表演過
*/
private List<Boolean> isOk;
public List<String> getProgrameList() {
return programeList;
}
public void setProgrameList(List<String> programeList) {
this.programeList = programeList;
}
public List<Boolean> getIsOk() {
return isOk;
}
public void setIsOk(List<Boolean> isOk) {
this.isOk = isOk;
}
/**
* 初始化標記
*/
public void initial()
{
isOk = new ArrayList<Boolean>();
for(int i = 0; i < programeList.size(); i++)
{
isOk.add(new Boolean(false));
}
}
/**
* 介紹節目
*/
public void introduce()
{
synchronized(isOk)
{
for(int i = 0; i < isOk.size(); i++)
{
if(isOk.get(i) == true)
{
continue;
}
else
{
System.out.println("now, next programe is:" + programeList.get(i));
isOk.set(i, true);
break;
}
}
}
}
/**
* 詢問觀衆
*/
public void askAudience()
{
System.out.println("How do you feel?Is it excellent?");
}
}
切點類Actor
public class Actor {
/**
* 演員表演
*/
public void perform()
{
System.out.println("the actor is performing very hard...");
}
}
配置applicationContext.xml文件
<!-- 定義節目單 -->
<util:list id="programeList">
<value>Song:May I Love you?</value>
<value>Dance: hip hot</value>
</util:list>
<!-- Pojo切面 -->
<bean id="host" class="com.daniel.model.bean.Host" autowire="byName" init-method="initial"></bean>
<!-- 定義切面 -->
<aop:config>
<aop:aspect ref="host">
<!-- 定義切點,在方法perform被調用 -->
<aop:pointcut expression="execution(* *.perform(..))" id="perform"/>
<!-- 定義前置通知 -->
<aop:before method="introduce" pointcut-ref="perform"/>
<!-- 定義返回後通知 -->
<aop:after-returning method="askAudience" pointcut-ref="perform"/>
</aop:aspect>
</aop:config>
<!-- 定義演員 -->
<bean id="Jay" class="com.daniel.model.bean.Actor"></bean>
最後測試一下:
public static void main(String[] args) {
// TODO Auto-generated method stub
Actor jay = (Actor) new ClassPathXmlApplicationContext("applicationContext.xml").getBean("Jay");
jay.perform();
}
運行結果:
now, next programe is:Song:May I Love you?
the actor is performing very hard。。。
How do you feel?Is it excellent?
恩,其實Jay(周杰倫),唱歌還是不錯的。