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(周杰伦),唱歌还是不错的。