1. 程式人生 > >Spring AOP 環繞通知

Spring AOP 環繞通知

Spring AOP的環繞通知和前置、後置通知有著很大的區別,主要有兩個重要的區別:

1)目標方法的呼叫由環繞通知決定,即你可以決定是否呼叫目標方法,而前置和後置通知是不能決定的,它們只是在方法的呼叫前後執行通知而已,即目標方法肯定是要執行的。joinPoint.proceed()就是執行目標方法的程式碼。

2)環繞通知可以控制返回物件,即可以返回一個與目標物件完全不同的返回值。雖然這很危險,但是卻可以做到。

下面的例子使用環繞通知,完成日誌寫入。

1)Spring配置檔案加入AOP定義

    <!--配置第三方平臺請求日誌切面-->  
    <bean id="logHandler" class="com.test.LogHandler" />  
    <aop:config>  
        <aop:aspect id="logAspect" ref="logHandler">  
            <aop:pointcut id="logPointCut" expression="execution(public * com.test.itf.*Ctr.*Hdl(..))"/>                
            <aop:around method="doAround"  pointcut-ref="logPointCut"/>  
        </aop:aspect>  
    </aop:config>  
2)通知處理類的定義
public class LogHandler {
	
	Logger logger = LoggerFactory.getLogger(LogHandler.class);
	
	@Resource(name="logService")
	private LogService logService; 
	
	public Object doAround(ProceedingJoinPoint joinPoint){
		try{
			Object ret = joinPoint.proceed(); //執行目標方法
			Object[] args =joinPoint.getArgs(); //獲取目標方法引數
			String arg0 = joinPoint.getSignature().getDeclaringTypeName();
			HttpServletRequest request =null ;
			for(int i=0;i<args.length;i++){
				if(args[i] instanceof HttpServletRequest ){
					request = (HttpServletRequest) args[i];  //獲取request引數物件
					break;
				}
			}
			JdResponse resp = (JdResponse) ret;  //目標方法執行返回的物件
			ConsumerLog log = new ConsumerLog();
			log.setId(UuidUtil.get32UUID());
			log.setCreateDate(new Date());
			log.setAppId(request.getParameter("appId"));
			log.setNonceStr(request.getParameter("nonceStr"));
			log.setOutput(JSONObject.toJSONString(resp));
			log.setInput(getHttpParameters(request));
			logService.insertLog(log);  //寫入日誌表
			return resp;
			
		}catch(Throwable e){
			logger.error("error in logService doArround:",e);
			return new JdResponse(JdResponse.CODE.serverError,"系統錯誤",null);
		}
	}
ProceedingJoinPoint物件表示連線點物件,該類是JoinPoint的子介面。該物件由spring自動傳值,實現客戶端給具體實現類的引數傳遞。