Spring boot Aop 示例

需要的依赖

 

<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-aop -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-aop</artifactId>
    <version>2.1.6.RELEASE</version>
</dependency>

 

ASPECT

 



import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.sun.org.apache.xpath.internal.operations.String;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;

@Aspect
@Component
public class LogAspect {

    private final static Logger logger = LoggerFactory.getLogger(LogAspect.class);

    // * 表示所有返回类型  ..表示包及子包 * 表示所有类 .* 指类所有方法 (..) 代表所有参数
    @Pointcut("execution(public * com.gailguo.demo.controller..*.*(..))")
    public void controllerMethod() {
    }


    @Before("controllerMethod()")
    public void LogRequestInfo(JoinPoint joinPoint) throws Exception {

        logger.info("请求结果: Before  " );

        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();

        StringBuffer requestLog = new StringBuffer();
        requestLog.append("请求信息:")
                .append("URL = {" + request.getRequestURI() + "},\t")
                .append("HTTP_METHOD = {" + request.getMethod() + "},\t")
                .append("IP = {" + request.getRemoteAddr() + "},\t")
                .append("CLASS_METHOD = {" + joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName() + "},\t");

        if(joinPoint.getArgs().length == 0) {
            requestLog.append("ARGS = {} ");
        } else {
            requestLog.append("ARGS = " + new ObjectMapper().setSerializationInclusion(JsonInclude.Include.NON_NULL)
                    .writeValueAsString(joinPoint.getArgs()[0]) + "");
        }

        logger.info(requestLog.toString());
    }


    @AfterReturning( pointcut = "controllerMethod()")
    public void logResultVOInfo() throws Exception {
        logger.info("请求结果: after return " );
    }

    @After("controllerMethod()")
    public void logAfter(JoinPoint joinPoint){
        logger.info("请求结果: after  " );
    }


    @AfterThrowing("controllerMethod()")
    public void logException(JoinPoint joinPoint){
        logger.info("请求结果: after AfterThrowing " );
    }

    @Around("controllerMethod()")
    public Object logAround(ProceedingJoinPoint joinPoint) throws  Throwable{

        Object s=null;
        if(joinPoint.getArgs().length>0){
             s=joinPoint.getArgs()[0];
            logger.info("Around: 打印传参 "+s.toString() );
        }
        logger.info("Around  1");
        Object obj=joinPoint.proceed(new Object[]{"sss+"+s.toString()});
        logger.info("Around 2");
        return  obj;

    }

}

 

一个简单的controller

@RestController
@RequestMapping(path = "/aop")
public class MyController {


    @RequestMapping(path ="/test")
    public String   getTest(@RequestParam("id")String id){
        return  "111"+id;
    }
}

  

 

Pointcut 执行表达式的格式

参考 

https://elim.iteye.com/blog/2395255

  

1: execution(modifiers-pattern? ret-type-pattern declaring-type-pattern? name-pattern(param-pattern) throws-pattern?) 
除了返回类型模式(上面代码片断中的ret-type-pattern),

名字模式和参数模式以外,所有的部分都是可选的。

返回类型模式决定了方法的返回类型必须依次匹配一个连接点。

你会使用的最频繁的返回类型模式是 * ,它代表了匹配任意的返回类型。

一个全称限定的类型名将只会匹配返回给定类型的方法。名字模式匹配的是方法名。

你可以使用 * 通配符作为所有或者部分命名模式。

参数模式稍微有点复杂:() 匹配了一个不接受任何参数的方法, 而 (..) 匹配了一个接受任意数量参数的方法(零或者更多)。

模式 (*) 匹配了一个接受一个任何类型的参数的方法。

模式 (*,String) 匹配了一个接受两个参数的方法,第一个可以是任意类型,第二个则必须是String类型。

 
一些常见切入点表达式的例子

 

execution(public * *(..))  任意公共方法的执行;
execution(* set*(..))  任何一个以“set”开始的方法的执行; 
execution(* com.xyz.service.AccountService.*(..))   AccountService接口的任意方法的执行;
execution(* com.xyz.service.*.*(..))  定义在service包里的任意方法的执行;
execution(* com.xyz.service..*.*(..))  定义在service包或者子包里的任意方法的执行;

 

2. within 是用来指定类型的,指定类型中的所有方法将被拦截

 

3. bean 

   bean用于匹配当调用的是指定的Spring的某个bean的方法时。

    “bean(abc)”匹配Spring Bean容器中id或name为abc的bean的方法调用。

    “bean(user*)”匹配所有id或name为以user开头的bean的方法调用。

@Component
public class TestInfo {

    Logger logger= LoggerFactory.getLogger(TestInfo.class);

    public void  testInfo(){
        logger.info("这里是testInfo 方法");
    }
}

  

 

  @Pointcut("bean(testInfo)")
    public void controllerMethod2(){

    }

  

 @Around("controllerMethod2()")
    public Object logAround2(ProceedingJoinPoint joinPoint) throws  Throwable{


        logger.info("Around  testInfo 1");
        Object obj=joinPoint.proceed();
        logger.info("Around  testInfo 2");
        return  obj;

    }

  

  @Autowired
    TestInfo info;

    @RequestMapping(path ="/test")
    public String   getTest(@RequestParam("id")String id){
        info.testInfo();
        return  "111"+id;
    }

  

 

转载于:https://www.cnblogs.com/galibujianbusana/p/11163858.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值