springboot aop 切面日志

参考文章:简单的aop实现日志打印(切入点表达式)

@Pointcut语法详解

spring 注解aop切入点表达式怎么排除某些方法

目录

1.AOP核心概念

2.JoinPoint 对象

3.简单示例

4.切面文件--use

5.pom.xml文件:


1.AOP核心概念

#1、横切关注点
#  对哪些方法进行拦截,拦截后怎么处理,这些关注点称之为横切关注点

#2、切面(aspect)
#  类是对物体特征的抽象,切面就是对横切关注点的抽象

#3、连接点(joinpoint)
#  被拦截到的点,因为Spring只支持方法类型的连接点,所以在Spring中连接点指的就是被拦截到的方
#   法,实际上连接点还可以是字段或者构造器

#4、切入点(pointcut)
#  对连接点进行拦截的定义

#5、通知(advice)
#  所谓通知指的就是指拦截到连接点之后要执行的代码,通知分为前置、后置、异常、最终、环绕通知五类

#6、目标对象
#  代理的目标对象

#7、织入(weave)
#  将切面应用到目标对象并导致代理对象创建的过程

#8、引入(introduction)
#  在不修改代码的前提下,引入可以在运行期为类动态地添加一些方法或字段

2.JoinPoint 对象

JoinPoint对象封装了SpringAop中切面方法的信息,在切面方法中添加JoinPoint参数,就可以获取到封装了该方法信息的JoinPoint对象. 

 常用api:

方法名 功能
Signature getSignature(); 获取封装了署名信息的对象,在该对象中可以获取到目标方法名,所属类的Class等信息
Object[] getArgs(); 获取传入目标方法的参数对象
Object getTarget(); 获取被代理的对象
Object getThis(); 获取代理对象

3.简单示例

声明一个切面类,并把这个切面类加入到IOC容器中

@Component//加入IOC容器
@Aspect//表示这是一个切面类
public class LogAspect{
    // #====================spring 注解aop切入点表达式怎么排除某些方法=================#
    // @Pointcut("!execution(* aa.bb..*.set*(..)) && execution(* aa.bb..*.*(..)) ")
    // 如果是这种形式的法执行了很多其他方法,比如init。

    // @Pointcut("execution(* aa.bb..*.*(..)) && !execution(* aa.bb..*.set*(..)) ")
    // 这种形式还是都执行了 
    
    //value中为切入点表达式
    @Before(value="execution(public void com.bwlu.common.MathCalculatorImpl.*(..))")//前置通知
    public void showBeginLog(){
        System.out.println("AOP日志开始");
    }
    @After(value="execution(public void com.bwlu.common.MathCalculatorImpl.*(..))")//后置通知
    public void showReturnLog(){
        System.out.println("AOP方法结束");
    }
    @AfterThrowing(value="execution(public void com.bwlu.common.MathCalculatorImpl.*(..))")//异常通知
    public void showExceptionLog(){
        System.out.println("AOP方法异常");
    }
    @AfterReturning(value="execution(public void com.bwlu.common.MathCalculatorImpl.*(..))")//返回通知
    public void showAfterLog(){
        System.out.println("AOP方法最终返回");
    }
}

4.切面文件--use

package com.cloud.config;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
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.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;

/**
 * 实现Web层的日志切面
 * 对于同一个代理对象,可以同时有多个切面共同对它进行代理。
 * 可以在切面类上通过@Order(value=50)注解来进行设置, 值越小优先级越高
 */
@Component
@Aspect
@Order(1) 
public class WebLogAspect {
    private Logger log = LoggerFactory.getLogger(getClass());
    private ThreadLocal startTime = new ThreadLocal<>();

    /**
     * 定义一个切入点.
     * 解释下:
     * 

* ~ 第一个 * 代表任意修饰符及任意返回值. * ~ 第二个 * 任意包名 * ~ 第三个 * 定义在web包或者子包 * ~ 第四个 * 任意方法 * ~ .. 匹配任意数量的参数. */ @Pointcut("(execution(public * com.cloud..*Controller.*(..)))") public void webLog() { } @Before("webLog()") public void doBefore(JoinPoint joinPoint) throws UnsupportedEncodingException { startTime.set(System.currentTimeMillis()); // 接收到请求,记录请求内容 log.info("========================= before -- start ========================="); Signature signature = joinPoint.getSignature(); MethodSignature methodSignature = (MethodSignature) signature; log.info("CLASS_METHOD : " + methodSignature.getDeclaringTypeName() + "." + methodSignature.getName()); log.info("请求参数: 名称 值"); String[] argsNameArray = methodSignature.getParameterNames(); Object[] argsValueArray = joinPoint.getArgs(); if (argsNameArray == null || argsNameArray.length < 1) { log.info("args_name: null"); log.info("args_value: null"); } else { for (int i = 0; i < argsNameArray.length; i++) { log.info("args_name: " + argsNameArray[i]); String argValue = argsValueArray[i] != null ? argsValueArray[i].toString() : ""; if (argsNameArray[i].contains("encode")) { String str = URLDecoder.decode(argValue, "utf-8"); log.info("args_value: " + (str.length() > 200 ? str.substring(0, 200) + "..." : str)); } else { log.info("args_value: " + (argValue.length() > 200 ? argValue.substring(0, 200) + "..." : argValue)); } } } // 记录下请求内容 ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); if(attributes == null){ log.info("========================= before -- end ========================="); return; } HttpServletRequest request = attributes.getRequest(); log.info("IP : " + request.getRemoteAddr()); log.info("========================= before -- end ========================="); } @AfterReturning(returning="rvt", pointcut="webLog()") public void doAfterReturning(JoinPoint joinPoint, Object rvt) { log.info("========================= after -- start ========================="); log.info("CLASS_METHOD : " + joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName()); if(rvt != null){ String str = rvt.toString(); if (str.length() > 200) { str = str.substring(0, 200) + "..."; } log.info("return 返回值:"); log.info(str); } log.info("耗时(毫秒) : " + (System.currentTimeMillis() - startTime.get())); log.info("========================= after -- end ========================="); } }

5.pom.xml文件:



    4.0.0

    com.cloud
    cloud-base-parent
    
    0.0.1-SNAPSHOT

    
    pom

    
        org.springframework.boot
        spring-boot-starter-parent
        
        

        2.0.5.RELEASE
         
    

    
        UTF-8
        UTF-8
        1.8
        Finchley.SR2
    

    
        
        
            org.springframework.boot
            spring-boot-starter-web
        

        
        
            org.springframework.boot
            spring-boot-starter-aop
               
    

     
    
        
            
                org.springframework.cloud
                spring-cloud-dependencies
                ${spring-cloud.version}
                pom
                import
            
        
    
   
    
    
        
            spring-snapshots
            Spring Snapshots
            https://repo.spring.io/snapshot
            
                true
            
        
        
            spring-milestones
            Spring Milestones
            https://repo.spring.io/milestone
            
                false
            
        
    

 

你可能感兴趣的:(springboot,spring)