6.3.1. 声明一个切面
有了schema的支持,切面就和常规的Java对象一样被定义成application context中的一个bean。 对象的字段和方法提供了状态和行为信息,XML文件则提供了切入点和通知信息。
切面使用<aop:aspect>来声明,backing bean(支持bean)通过 ref 属性来引用:
<aop:config> <aop:aspect )可以象其他Spring bean一样被容器管理配置以及依赖注入。切入点可以在切面里面声明,这种情况下切入点只在切面内部可见。切入点也可以直接在<aop:config>下定义,这样就可以使多个切面和通知器共享该切入点。
一个描述service层中表示所有service执行的切入点可以如下定义:
<aop:config> <aop:pointcut />... </aop:aspect></aop:config>当需要连接子表达式的时候,'&'在XML中用起来非常不方便,所以关键字'and', 'or' 和 'not'可以分别用来代替'&', '||' 和 '!'。
注意这种方式定义的切入点通过XML id来查找,并且不能定义切入点参数。在基于schema的定义风格中命名切入点支持较之@AspectJ风格受到了很多的限制。
和@AspectJ风格一样,基于schema的风格也支持5种通知类型并且两者具有同样的语义。
After returning通知在匹配的方法完全执行后运行。和Before通知一样,可以在<aop:aspect>里面声明。例如:
<aop:aspect >retVal 的参数。 参数的类型强制匹配,和先前我们在@AfterReturning中讲到的一样。例如,方法签名可以这样声明:public void doAccessCheck(Object retVal) {...After throwing通知在匹配方法抛出异常退出时执行。在 <aop:aspect> 中使用after-throwing元素来声明:
<aop:aspect >dataAccessEx 的参数。 参数的类型强制匹配,和先前我们在@AfterThrowing中讲到的一样。例如:方法签名可以如下这般声明:public void doRecoveryActions(DataAccessException dataAccessEx) {...After (finally)通知在匹配方法退出后执行。使用 after 元素来声明:
<aop:aspect />...</aop:aspect>Around通知是最后一种通知类型。Around通知在匹配方法运行期的“周围”执行。 它有机会在目标方法的前面和后面执行,并决定什么时候运行,怎么运行,甚至是否运行。 Around通知经常在需要在一个方法执行前或后共享状态信息,并且是线程安全的情况下使用(启动和停止一个计时器就是一个例子)。 注意选择能满足你需求的最简单的通知类型(i.e.如果简单的before通知就能做的事情绝对不要使用around通知)。
Around通知使用 aop:around 元素来声明。 通知方法的第一个参数的类型必须是 ProceedingJoinPoint 类型。 在通知的主体中,调用 ProceedingJoinPoint的proceed() 方法来执行真正的方法。 proceed 方法也可能会被调用并且传入一个 Object[] 对象 - 该数组将作为方法执行时候的参数。 参见 Section 6.2.4.5, “环绕通知(Around Advice)” 中提到的一些注意点。
<aop:aspect >doBasicProfiling 通知的实现和@AspectJ中的例子完全一样(当然要去掉注解):public Object doBasicProfiling(ProceedingJoinPoint pjp) throws Throwable { // start stopwatch Object retVal = pjp.proceed(); // stop stopwatch return retVal;}
<aop:aspect id="aop_aspect_frisetclass" ref="AopAdvice">
<!-- 定义个After增强处理,直接指定切入点表达式,以切面 Bean 中的 Release() 方法作为增强处理方法 -->
<aop:around pointcut="execution(* cn.damai.std.mypoxy.FrisetClass.*(..))" method="doBasicProfiling" />
<aop:before pointcut="execution(* cn.damai.std.mypoxy.FrisetClass.addStudent(..))" method="aopbeforemethod"/>
<aop:after pointcut="execution(* cn.damai.std.mypoxy.FrisetClass.addStudent(..))" method="aopaftermethod"/>
<aop:after-returning pointcut="execution(* cn.damai.std.mypoxy.FrisetClass.getStudentScores(..))" returning="val" method="aopafterreturnmethod"/>
<aop:after-throwing pointcut="execution(* cn.damai.std.mypoxy.FrisetClass.getStudentScores(..))" throwing="exdate" method="aopafterthrowmethod"/>
</aop:aspect>
</aop:config>
// start stopwatch
Object retVal = pjp.proceed();
if(pjp.getArgs()!=null){
for(Object o : pjp.getArgs()){
logger.debug("参赛="+o);
}
}
// stop stopwatch
return retVal;
}
public void aopbeforemethod(){
logger.debug("执行 方法 aopbeforemethod ");
}
public void aopaftermethod(){
}
public void aopafterreturnmethod(Object val){
logger.debug("执行 方法 aopafterreturnmethod 返回值"+val);
}
public void aopafterthrowmethod(Throwable exdate){
logger.debug("执行 方法 aopafterthrowmethod "+exdate);
}