spring aop 切面測試
阿新 • • 發佈:2019-02-17
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,除非有必須釋放的資源,但仍然需注意將e丟擲給spring,並且finally不能由任何返回,否則spring同樣認為沒有異常發生
processTx中,
result=pjp.proceed(args);
前後,Spring捕捉到異常,會進行一系列處理,回滾等等,原則上也不進行try catch,
但此處考慮到異常的返回值,此處顯式回滾,並定義異常返回值,在集中處理器中自行處理異常