springboot2 AOP切面实现打印任意类的方法入参、出参、耗时

自定义注解!aop编程

功能:不但可以打印Controller方法里的入参和出参,也能打印Service类或任意一个类里的方法入参和出参。

注意: AOP默认如果同一个类有A方法、B方法,如果A调用了B, 则B方法上的注解不生效,必须是非同类的发起的调用方法注解才生效。

自定义注解 printLog
/**
 * 日志切面注解
 *
 * @author zhaoyang10
 * @date 2020/7/27
 */
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
@Documented
public @interface PrintLog {

    /**
     * 日志方法描述信息
     */
    String info() default "";
}

注解切面实现

import com.xx.xx.fms.common.util.FastJsonUtil;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.context.annotation.Profile;
import org.springframework.core.DefaultParameterNameDiscoverer;
import org.springframework.core.ParameterNameDiscoverer;
import org.springframework.stereotype.Component;

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

/**
 * 打印日志切面
 *
 * @author zhaoyang10
 * @date 2020/7/27
 */
@Slf4j
@Aspect
@Component
// @Profile({"dev", "test", "uat"})  // 生效环境配置
public class PrintLogAspect {

    private static ParameterNameDiscoverer pnd = new DefaultParameterNameDiscoverer();

    @Pointcut("@annotation(com.weibo.bop.fms.common.support.log.PrintLog)")
    public void printLog() {
        // do nothing
    }

    @Before("printLog()")
    public void doBefore(JoinPoint joinPoint) {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        String targetClassName = signature.getDeclaringType().getSimpleName();
        String methodName = signature.getName();

        PrintLog printLog = signature.getMethod().getAnnotation(PrintLog.class);
        String desc = printLog.info();

        log.info("Method info: {}.{} {}, params: {}", targetClassName, methodName, desc, FastJsonUtil.toJson(getFieldsName(joinPoint)));
    }

    @Around("printLog()")
    public Object doAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        long startTime = System.currentTimeMillis();

        Object result = proceedingJoinPoint.proceed();

        log.info("Method result: {}, cost: {}ms", FastJsonUtil.toJson(result), System.currentTimeMillis() - startTime);
        return result;
    }

    /**
     * 获取参数列表
     */
    private static Map<String, Object> getFieldsName(JoinPoint joinPoint) {
        // 参数值
        Object[] args = joinPoint.getArgs();
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        String[] parameterNames = pnd.getParameterNames(method);
        if (parameterNames != null) {
            Map<String, Object> paramMap = new HashMap<>(parameterNames.length);
            for (int i = 0; i < parameterNames.length; i++) {
                paramMap.put(parameterNames[i], args[i]);
            }
            return paramMap;
        }
        return Collections.emptyMap();
    }
}

使用示例

// Controller方法
@PrintLog(info = "测试方法test2")
@GetMapping("/test/test2")
public ApiResult<String> test2(@RequestParam String name, String age) {

	return ApiResult.ok();
}

// 非Controller方法
@PrintLog(info = "测试方法list")
public TestRepDTO list(TestReqDTO dto){
	ThreadUtil.sleep(3000);
	
	TestRepDTO repDTO = new TestRepDTO();
	// do something
	return repDTO;
}
Spring Boot实现AOP面向切面编程的具体方法如下: 1. 首先,你需要在项目的pom.xml文件中添加spring-boot-starter-aop依赖。可以考以下代码: ``` <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId> </dependency> ``` 2. 然后,你需要编写一个用于拦截的bean。这个bean将包含你想要在目标方法执行前后执行的逻辑。你可以使用注解或者编程方式来定义切面。例如,你可以使用@Aspect注解来定义一个切面,然后在切面方法上使用@Before、@After等注解来定义具体的拦截行为。 3. 接下来,你需要将切面应用到目标对象上,创建代理对象。这个过程称为织(Weaving)。在Spring Boot中,你可以使用@EnableAspectJAutoProxy注解来启用自动代理,它会根据切面定义自动创建代理对象。 总而言之,Spring Boot实现AOP面向切面编程的具体方法包括:添加依赖、编写用于拦截的bean,以及启用自动代理。这样就能实现在目标方法执行前后执行特定逻辑的效果了。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [SpringBoot整合aop面向切面编程过程解析](https://download.csdn.net/download/weixin_38689551/12743012)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* *3* [SpringBoot实现AOP面向切面编程](https://blog.csdn.net/weixin_52536274/article/details/130375560)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值