AOP中ProceedingJoinPoint獲取目標方法,參數,註解

private void saveLog(ProceedingJoinPoint jp,long time)throws Throwable {
   	 	package com.cy.pj.common.aspect;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Date;
 
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
 
import com.cy.pj.common.annotation.RequiredLog;
import com.cy.pj.common.util.IPUtils;
import com.cy.pj.sys.entity.SysLog;
import com.cy.pj.sys.service.SysLogService;
 
import lombok.extern.slf4j.Slf4j;
/**
 * @Aspect 描述的類爲切面類,此類中實現:
 * 1)切入點(Pointcut)的定義
 * 2)通知(advice)的定義(擴展功能)
 */
@Slf4j
@Aspect
@Component
public class SysLogAspect {
	 /**
	  * @Pointcut 註解用於描述或定義一個切入點
	    *  切入點的定義需要遵循spring中指定的表達式規範
	    例如:("bean(sysMenuServiceImpl)")爲切入點表達式
	    的一種定義方式。
	  */
	 //bean(bean名稱或一個表達式)
     //@Pointcut("bean(sysMenuServiceImpl)")
	 @Pointcut("@annotation(com.cy.pj.common.annotation.RequiredLog)")
	 public void logPointCut() {}
     
     /**
      * @Around 註解描述的方法爲一個環繞通知方法,
            * 在此方法中可以添加擴展業務邏輯,可以調用下一個
              切面對象或目標方法
      * @param jp 連接點(此連接點只應用@Around描述的方法)
      * @return
      * @throws Throwable
      */
     @Around("logPointCut()")
     public Object aroundAdvice(ProceedingJoinPoint jp)
     throws Throwable{
    	 long start=System.currentTimeMillis();
    	 log.info("start:"+start);
    	 Object result=jp.proceed();//調用下一個切面或目標方法
    	 long end=System.currentTimeMillis();
    	 log.info("end:"+end);
    	 //記錄日誌(用戶行爲信息)
    	 saveLog(jp,(end-start));
    	 return result;
     }
     @Autowired
     private SysLogService sysLogService;
     //日誌記錄
     private void saveLog(ProceedingJoinPoint jp,long time)throws Throwable {
    	 //1.獲取用戶行爲日誌(ip,username,operation,method,params,time,createdTime)
         //獲取類的字節碼對象,通過字節碼對象獲取方法信息
    	 Class<?> targetCls=jp.getTarget().getClass();
         //獲取方法簽名(通過此簽名獲取目標方法信息)
         MethodSignature ms=(MethodSignature)jp.getSignature();
         //獲取目標方法上的註解指定的操作名稱
         Method targetMethod=
         targetCls.getDeclaredMethod(
        		 ms.getName(),
        		 ms.getParameterTypes());
         RequiredLog requiredLog=
         targetMethod.getAnnotation(RequiredLog.class);
         String operation=requiredLog.value();
         System.out.println("targetMethod="+targetMethod);
    	 //獲取目標方法名(目標類型+方法名)
         String targetClsName=targetCls.getName();
         String targetObjectMethodName=targetClsName+"."+ms.getName();
         //獲取請求參數
    	 String targetMethodParams=Arrays.toString(jp.getArgs());
    	 //2.封裝用戶行爲日誌(SysLog)
    	 SysLog entity=new SysLog();
    	 entity.setIp(IPUtils.getIpAddr());
    	 entity.setUsername("admin");
    	 entity.setOperation(operation);
    	 entity.setMethod(targetObjectMethodName);
    	 entity.setParams(targetMethodParams);
    	 entity.setTime(time);
    	 entity.setCreatedTime(new Date());
    	 //3.調用業務層對象方法(saveObject)將日誌寫入到數據庫
    	 sysLogService.saveObject(entity);
     }
}
    }

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章