此案例基于第一篇而写,初学者可先看第一篇熟悉springAOP,再看此篇。
此篇文章只对spring配置文件做改进。
AOP操作中,通常会将前置通知,后置通知,异常通知和最终通知结合使用,如下例:
<!-- 配置AOP -->
<aop:config>
<!-- 配置切面 -->
<aop:aspect id="trans" ref="jdbcTrans">
<!-- 配置通知:前置通知 -->
<aop:before method="beginTransaction" pointcut="execution(public void cn.com.lzxh.service.impl.UserServiceImpl.saveUser())"/>
<!-- 后置通知 -->
<aop:after-returning method="commitTransaction" pointcut="execution(public void cn.com.lzxh.service.impl.UserServiceImpl.saveUser())"/>
<!-- 异常通知 -->
<aop:after-throwing method="rollbackTransaction" pointcut="execution(public void cn.com.lzxh.service.impl.UserServiceImpl.saveUser())"/>
<!-- 最终通知 -->
<aop:after method="releaseTransaction" pointcut="execution(public void cn.com.lzxh.service.impl.UserServiceImpl.saveUser())"/>
</aop:aspect>
</aop:config>
<!-- 添加如下配置防止spring AOP配置混乱 -->
<aop:aspectj-autoproxy proxy-target-class="true"/>
前置通知在业务代码执行之前执行,后置通知在业务代码之后执行,异常通知在业务代码发生异常时执行,最终通知在最后执行,以上程序的执行过程类似如下代码:
try {
jt.beginTransaction();
us.saveUser();
//int i = 1 / 0;
jt.commitTransaction();
} catch (Exception e) {
jt.rollbackTransaction();
e.printStackTrace();
} finally {
jt.releaseTransaction();
}
用上面的方法配置pointcut显得十分繁琐,可以进行简化,如下:
<!-- 配置AOP -->
<aop:config>
<!-- 配置切面 -->
<aop:aspect id="trans" ref="jdbcTrans">
<!-- 配置通知:前置通知 -->
<aop:before method="beginTransaction" pointcut-ref="point"/>
<!-- 后置通知 -->
<aop:after-returning method="commitTransaction" pointcut-ref="point"/>
<!-- 异常通知 -->
<aop:after-throwing method="rollbackTransaction" pointcut-ref="point"/>
<!-- 最终通知 -->
<aop:after method="releaseTransaction" pointcut-ref="point"/>
<!-- 切点配置 -->
<aop:pointcut id="point" expression="execution(public void cn.com.lzxh.service.impl.UserServiceImpl.saveUser())"/>
</aop:aspect>
</aop:config>
<!-- 添加如下配置防止spring AOP配置混乱 -->
<aop:aspectj-autoproxy proxy-target-class="true"/>
将<aop:pointcut/>单独作为一个标签配置在切面内部,或切面外部,但是要注意,如果单独配置在切面外部,则只能配置在切面上面,不能配置在切面下面,如下:
<!-- 配置AOP -->
<aop:config>
<!-- 切点配置 -->
<aop:pointcut id="point" expression="execution(public void cn.com.lzxh.service.impl.UserServiceImpl.saveUser())"/>
<!-- 配置切面 -->
<aop:aspect id="trans" ref="jdbcTrans">
<!-- 配置通知:前置通知 -->
<aop:before method="beginTransaction" pointcut-ref="point"/>
<!-- 后置通知 -->
<aop:after-returning method="commitTransaction" pointcut-ref="point"/>
<!-- 异常通知 -->
<aop:after-throwing method="rollbackTransaction" pointcut-ref="point"/>
<!-- 最终通知 -->
<aop:after method="releaseTransaction" pointcut-ref="point"/>
</aop:aspect>
</aop:config>
<!-- 添加如下配置防止spring AOP配置混乱 -->
<aop:aspectj-autoproxy proxy-target-class="true"/>
另外,切点表达式的配置也可以简化,普通写法如下:<aop:pointcut id="point" expression="execution(public void cn.com.lzxh.service.impl.UserServiceImpl.saveUser())"/>,此配置中的切点只能是一个方法,可简化为如下所示:
expression="execution(* * cn.com.lzxh.service.impl.*.*(..))",该表达式代表任何修饰符修饰的,具有任何返回类型的,impl包下的所有类的所有方法都是切点,这些方法可以有任意个参数。