AOP的具體實踐-簡化結果返回的處理

m53469發表於2021-09-09

原因:

  以前學習Spring的時候著重學習過AOP概念,但是一直也沒有用上,唯一碰到過的就是Spring內建的事務管理。現在碰到過一些結果後面的操作適合用到,所以這裡就拿出來用一下,並且複習一下落下的知識。

概念:

  基本概念這個博主解釋的比較清楚,如果有不懂的可以去看一下。https://blog.csdn.net/csh624366188/article/details/7651702

  在我的認識裡,如果某些方法重複性特別高,可以抽象出來形成一個切面,則可以使用AOP來簡化程式碼,即在方法的某些部分動態的新增某些方法,起到簡化程式碼的作用。

具體需求:

  專案的Service層透過webService獲取到資料,需要對獲取到的資料進行判斷處理,對其異常資訊作出記錄和丟擲異常。同時還需要在進入和結束方法的時候進行日誌記錄。

知識點:

  配置方法:

  在這裡使用的是註解的方式來配置的AOP,首先,要保證專案中除了Spring基本包以外還包含aopalliance-1.0.jar,aspectjrt-1.8.7.jar,aspectjweaver-1.8.7.jar,cglib-nodep-3.2.4.jar這四個jar包,這裡將其打包放到百度雲,如果有需要的可以去下載。連結: 密碼:0uea

  Spring配置新增如下, 新增需要新增Spring的頭部內容

  注意aop不能新增到static方法上面。

      // 掃描AOP
    <!-- 這裡配置後就不用再使用bean標籤配置bean了 --&gt
    
    <!-- 去哪個包掃描生成bean --&gt
    

 

  首選建立切面類:其中的afterReturning就是主要的切面方法,用於對返回值進行判斷並且進行對應的操作,這樣可以不用再每個方法中都寫一次。

  
  @Pointcut("execution(* com.dazhong.jnfy.alipay.service.impl.*.*(..))"):表示AOP會代理那些方法,這裡則表示com.dazhong.jnfy.alipay.service.impl包下面所有方法都會執行
  @After("picter()"):後置通知
  @Before("picter()"):前置通知
 

圖片描述

package com.dazhong.jnfy.alipay.aop;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.json.JSONObject;
import org.springframework.stereotype.Component;

import com.dazhong.jnfy.alipay.exception.ConnectionException;
import com.dazhong.jnfy.alipay.exception.ResultErrorException;
import com.dazhong.utils.LogUtil;@Component
@Aspect
public class ServiceAop {

    @Pointcut("execution(* com.dazhong.jnfy.alipay.service.impl.*.*(..))")
    public void picter() {
    }

    /**
    * @Description: 對返回值進行處理
    * @param point
    * @param rvt
    * @throws ResultErrorException 
    */
    @AfterReturning(returning = "rvt", pointcut = "execution(* com.dazhong.jnfy.alipay.service.impl.*.*(..))")
    public void afterReturning(JoinPoint point, Object rvt) throws Exception {  // Object rvt則是方法返回值,這裡變數名稱要和註解retruning值相同
        String[] strs = point.getSignature().getDeclaringTypeName().split("\.");
        String fullname = strs[strs.length - 1] + "." + point.getSignature().getName();

        JSONObject root = (JSONObject) rvt;

        if (rvt == null) {
            throw new ConnectionException("WebService連線失敗" + fullname);
        } else if (!root.has("resultCode") || !root.get("resultCode").toString().equals("0")) {
            // 返回資料異常
            throw new ResultErrorException("WebService 返回結果異常:" + root.toString());
        }
    }

    @Before("picter()")
    public void before(JoinPoint point) {
        String[] strs = point.getSignature().getDeclaringTypeName().split("\.");
        String fullname = strs[strs.length - 1] + "." + point.getSignature().getName();
        LogUtil.info("進入方法:" + fullname);
    }

    @After("picter()")
    public void after(JoinPoint point) {
        String[] strs = point.getSignature().getDeclaringTypeName().split("\.");
        String fullname = strs[strs.length - 1] + "." + point.getSignature().getName();
        LogUtil.info("方法結束:" + fullname);
    }

}

圖片描述

  獲取引數/方法名:

    如果需要獲取目標方法的引數/名字,則需要在切面的方法中新增變數 JoinPoint point,透過這個物件來進行獲取。

     String allname = point.getSignature().getDeclaringTypeName();  // 獲取整個路徑 包名+類名     System.out.println(allname);
     String[] split = allname.split("\.");
     System.out.println("目標方法:" + split[split.length - 1] + "." + point.getSignature().getName());  // point.getSignature().getName() 獲取方法名
     System.out.println("@Before:引數為:" + Arrays.toString(point.getArgs()));  // 獲取目標方法的引數 point.getArgs()

 

 

  結果: 紅框內容就是AOP自動新增的。

  圖片描述

  剩餘程式碼:

  目標方法:

  

    public JSONObject test() throws Exception{
        System.out.println("目標方法執行");
        JSONObject js = new JSONObject();
        js.put("resultCode", "-1");
        return js;
    }

  測試方法:

  

圖片描述

    public static void main(String[] args) {
        ApplicationContext appCtx = new ClassPathXmlApplicationContext("applicationContext.xml");
        ReserveServiceImpl b = (ReserveServiceImpl) appCtx.getBean("reserveServiceImpl");
        JSONObject js = new JSONObject();
        js.put("s", "111");
        try {
            //JSONObject allDept = b.getDocterByTimeAndDept("YYKS002", "20180711");            b.test();
        } catch (Exception e) {
            System.out.println(e);
        }
    }

圖片描述

 原文出處:https://www.cnblogs.com/liyuhui-Z/p/9468756.html


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/2819/viewspace-2811743/,如需轉載,請註明出處,否則將追究法律責任。

相關文章