1. 程式人生 > >spring aop 切面測試

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,除非有必須釋放的資源,但仍然需注意將e丟擲給spring,並且finally不能由任何返回,否則spring同樣認為沒有異常發生

processTx中,

result=pjp.proceed(args);

前後,Spring捕捉到異常,會進行一系列處理,回滾等等,原則上也不進行try catch,

但此處考慮到異常的返回值,此處顯式回滾,並定義異常返回值,在集中處理器中自行處理異常