spring aop 切面测试
spring 配置 aop
<aop:config> <aop:aspect id="asp1" ref="monitorApi"> <!-- 配置一个切入点,相当于@Pointcut --> <aop:pointcut expression="execution(* com.xxx.xxx.impl.service.*.*(..))" id="simplePointcut"/> <aop:before method="serviceBefore" pointcut-ref="simplePointcut" /> <aop:after method="release" pointcut-ref="simplePointcut" /> <aop:after-returning method="serviceAfter" pointcut-ref="simplePointcut" returning="rvt" /> <aop:around method="processTx" pointcut-ref="simplePointcut" /> <aop:after-throwing pointcut-ref="simplePointcut" method="afterThrow" throwing="ex"/> </aop:aspect> </aop:config>
切面类:
package com.changhang.urgoo.impl.utils; import com.changhang.urgoo.impl.entity.result.MesResult; import com.changhang.urgoo.impl.entity.result.SpResult; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.ProceedingJoinPoint; import org.springframework.transaction.interceptor.TransactionAspectSupport; public class MonitorApi{ /** * 通知前 * @date 2016年9月27日 上午9:18:10 * @Title before * @Description * @param jp void * @throws */ public void serviceBefore(JoinPoint jp) { // System.out.println("被代理方法名字:"+jp.getSignature().getName()); // System.out.println("被代理方法参数:"+jp.getArgs().toString()); // System.out.println("被代理对象:"+jp.getTarget()); // System.out.println("模拟权限验证"); } /** * * @date 2016年9月27日 上午9:18:29 * @Title log * @Description * @param jp * @param rvt void * @throws */ public void serviceAfter(JoinPoint jp, Object rvt){ long start= System.currentTimeMillis(); System.out.println("被代理方法名字:"+jp.getSignature().getName()); System.out.println("被代理方法参数:"+jp.getArgs()); System.out.println("被代理对象:"+jp.getTarget()); System.out.println("被代理对象的返回值"+rvt); System.out.println("现在调用的是日志管理"); long end= System.currentTimeMillis(); System.err.println(">>>>>>>>>>>日志处理时间共:"+(end-start)+" 毫秒"); } /** * * @date 2016年9月27日 上午9:18:53 * @Title processTx * @Description * @param pjp * @return * @throws Throwable Object * @throws */ public Object processTx(ProceedingJoinPoint pjp) throws Throwable { long start= System.currentTimeMillis(); System.out.println("现在调用的是事务开启"); //得到业务方法的参数 Object[] args=pjp.getArgs(); System.out.println("业务方法的参数:"+args.toString()); // Object result = pjp.proceed(args); //被代理对象的业务方法 Object result = null; try{ result=pjp.proceed(args); System.out.println("现在调用的是事务提交或回滚"); long end= System.currentTimeMillis(); System.err.println(">>>>>>>>>>>事物处理时间共:"+(end-start)+" 毫秒"); return result; } catch (Exception e) { // e.printStackTrace(); // 此处不进行打印,交由spring委托afterThrow进行打印 TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); SpResult sr = new SpResult(); sr.setHeaderCode("400"); sr.setHeaderMessage(MesResult.messageInfo(MesResult.SERVER_BUSY, null)); sr.setBody(null); return sr; //throw e; } finally { ; } } /** * * @date 2016年9月27日 上午9:19:43 * @Title release * @Description void * @throws */ public void release(){ System.out.println("资源已经被释放!"); } //配置抛出异常后通知,使用在方法aspect()上注册的切入点 public void afterThrow(JoinPoint jp, Exception ex){ long start= System.currentTimeMillis(); System.out.println("被代理方法名字:"+jp.getSignature().getName()); System.out.println("被代理方法参数:"+jp.getArgs()); System.out.println("被代理对象:"+jp.getTarget()); System.out.println("被代理对象的返回值"+ex); ex.printStackTrace(); System.out.println("现在调用的是异常管理"); long end= System.currentTimeMillis(); System.err.println(">>>>>>>>>>>异常处理时间共:"+(end-start)+" 毫秒"); System.err.println("------------afterThrow---------------"); } }
service:
@Service @Transactional public class TestService extends BaseService{ @Autowired private TestAccessor testAccessor; public SpResult aop(Map<String,String> map) { SpResult sp = new SpResult(); testAccessor.insertTest(map); testAccessor.selectTest(); return sp; } public SpResult withoutaop(Map<String,String> map) { SpResult sp = new SpResult(); try{ testAccessor.insertTest(map); testAccessor.selectTest(); } catch (Exception e) { // e.printStackTrace(); //TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); throw new RuntimeException(e); } finally { ; } return sp; } }
其中 insertTest正常,selectTest异常
函数aop完全不考虑异常,由Spring来全程捕捉处理,到了processTx中,集中处理
函数withoutaop则有try catch代码,扔出throw new RuntimeException(e);,效果等同于aop,如果此处没有扔出,则切面代理会走around -------- after-returning,因为spring不认为由异常发生,
扔出后,走around ------- after-throwing
注意,在catch中一般需要throw出异常,否则自行处理则spring认为没有异常在service发生,将不会回滚,当然也可以在catch中显式回滚:
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
但是这样所有函数代码变得冗长不好维护,不如不进行try catch操作,原则上service层不进行try catch,有必须释放的资源则finally throw return ,但仍然需注意将e抛出给spring,并且finally不能由任何返回,否则spring同样认为没有异常发生(finally throw return )
processTx中,
result=pjp.proceed(args);
前后,Spring捕捉到异常,会进行一系列处理,回滚等等,原则上也不进行try catch,
但此处考虑到异常的返回值,此处显式回滚,并定义异常返回值,在集中处理器中自行处理异常