AdSense

網頁

2020/6/1

Spring AOP get method advice annotation and parameters

在Spring AOP透過從annotation advice取得方法的annotation。

也就是對方法上標注的annotation做advice切面,例如「Spring AOP 使用annotation 對方法做log」。

下面的DemoController.doTest()透過標註@LogInfo來被LogInfoAdvice做advice。

DemoController

package com.abc.demo.controller;

import com.abc.demo.annotation.LogInfo;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.RequestParam

@RestController
public class DemoController {

    @LogInfo(message = "hello") // <-- advice
    @GetMapping(value = "/test")
    public void doTest(@RequestParam String name, @RequestParam Integer age) {

        System.out.println("do something...");

    }
}

ProceedingJoinPoint取得annotation@LogInfo的方法如下。透過從JoinPoint取得MethodSignature來得到annotation物件。

LogInfoAdvice

package com.abc.demo.aop;

import com.cherri.acs_kernel.annotation.LogInfo;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.util.HashMap;
import java.util.Map;

@Aspect
@Component
public class LogInfoAspect {

    @Autowired
    private ObjectMapper objectMapper;

    @Around("@annotation(com.abc.demo.annotation.LogInfo)")
    public Object logInfo(ProceedingJoinPoint joinPoint) throws Throwable {

        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        String className = signature.getDeclaringType().getSimpleName(); // 取得方法所在的類別名稱
        Method method = signature.getMethod(); // 取得被annotation標注的方法
        String methodName = method.getName(); // 取得方法名稱

        LogInfo logInfo = method.getAnnotation(LogInfo.class); // 取得標注的annotation

        Parameter[] parameters = method.getParameters(); // 取得方法輸入參數資訊
        Object[] args = joinPoint.getArgs(); // 取得輸入參數值
        String paramsMapJsonString = getParamsMapJsonString(parameters, args); // 把輸入參數轉成json字串
        /* e.g.
        {
            "name" : "john",
            "age" : 45,
        }
         */
       
        ...
        Object object = joinPoint.proceed();
        ...

        return object;
    }

    private String getParamsMapJsonString(Parameter[] parameters, Object[] args) {
        Map<String, Object> params = new HashMap<>();
        for (int i = 0 ; i < parameters.length; i++) {
            params.put(parameters[i].getName(), args[i]);
        }
        try {
            return objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(params);
        } catch (JsonProcessingException e) {
            log.error("parse args to json error, args={}", args);
            return "";
        }
    }

}

沒有留言:

AdSense