第一个链接思路很清晰,讲的也很详细,第二个链接讲了自定义注解


为了便于自己理解做了以下整理


目录

1.aspectj基本概念

2.添加aop依赖

3.进行切面处理

(1)切面类

(2)自定义注解

(3)controller和serviceimpl

4.定义切点时包扫描路径的表达式怎么写



1.aspectj基本概念




spring boot 全局时间 设置时区 springboot 全局日志_spring boot


下面两个类JoinPoint和ProceedingJoinPoint,ProceedingJoinPoint类在切面类中最后一个方法doAround()中用到了(已注释的部分),用于获取自定义注解



spring boot 全局时间 设置时区 springboot 全局日志_java_02


2.添加aop依赖


<!-- aop 依赖 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-aop</artifactId>
</dependency>


3.进行切面处理


主要是在切面类中设置切入点(指定包扫描路径),然后定义织入方式(方法前,方法后等)


也可以自定义注解,但是在我看来,最终还是要在切面类指定包扫描路径的,自定义注解无非是传入一些自定义参数,暂时没有探索别的用处


自定义注解的部分已被注释,直接放开注释就能使用


(1)切面类


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;
import java.util.Arrays;


@Aspect
@Component
public class WebLogAspect {


    // 获取日志类,方便直接在控制台输出统一格式的日志信息
    private final static Logger logger = LoggerFactory.getLogger(WebLogAspect.class);


    /**
     * 以 controller 包下定义的所有请求为切入点
     */
    @Pointcut("execution(public * com.tt.test.controller.*.*(..))")
    public void webLog() {
    }


    /**
     * 在切点之前织入
     *
     * @param joinPoint
     * @throws Throwable
     */
    @Before("webLog()") // webLog():是你@Pointcut注解的方法名
    public void doBefore(JoinPoint joinPoint) throws Throwable {
        // 开始打印请求日志
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();


        // 打印请求相关参数
        logger.info("========================================== Start ==========================================");
    }


    /**
     * 在切点之后织入
     *
     * @throws Throwable
     */
    @After("webLog()")
    public void doAfter() throws Throwable {
        logger.info("=========================================== End ===========================================");
        // 每个请求之间空一行
        logger.info("");
    }


    /**
     * 环绕
     *
     * @param proceedingJoinPoint
     * @return
     * @throws Throwable
     */
    @Around("webLog()")
    public Object doAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        long startTime = System.currentTimeMillis();
        Object result = proceedingJoinPoint.proceed();
        //获取自定义注解中传入的desc
        /*Signature signature = proceedingJoinPoint.getSignature();
        MethodSignature methodSignature = (MethodSignature) signature;
        Method method = methodSignature.getMethod();
        EagleEye eagleEye = method.getAnnotation(EagleEye.class);
        String desc=eagleEye.desc();
        logger.info("Request desc   : {}", desc);*/
        logger.info("Request Args   : {}", Arrays.asList(result).toString());
        // 执行耗时
        logger.info("Time-Consuming : {} ms", System.currentTimeMillis() - startTime);
        return result;
    }
}


(2)自定义注解


import java.lang.annotation.*;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@Documented
public @interface EagleEye {
    //描述,默认为空
    String desc() default "";
}


(3)controller和serviceimpl


要想serviceimpl中的方法也被aop织入,需要把serviceimpl文件移动到controller文件夹中,因为切面类中定义了包扫描路径,或者不移动文件夹而是在切面类中定义切点的时候把serviceimpl的包路径也包含进去


controller


import com.tt.test.config.EagleEye;
import com.tt.test.service.EagleService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;


/**
* 测试aop全局日志
*/
@RestController
@RequestMapping("/eagle")
public class EagleController {
    @Autowired
    private EagleService eagleService;


    @RequestMapping("/h1")
//    @EagleEye(desc = "hello1")
    public String h1(){return eagleService.h1();}


    @RequestMapping("/h2")
//    @EagleEye(desc = "hello2")
    public String h2(){return eagleService.h2();}
}


serviceimpl实现类(service层接口省略)


import com.tt.test.config.EagleEye;
import com.tt.test.service.EagleService;
import org.springframework.stereotype.Service;


@Service
public class EagleServiceImpl implements EagleService {
    @Override
//    @EagleEye(desc = "hello1-service")
    public String h1() {
        String s="s1";
        return s;
    }


    @Override
//    @EagleEye(desc = "hello2-service")
    public String h2() {
        String s="s2";
        return s;
    }
}


4.定义切点时包扫描路径的表达式怎么写



spring boot 全局时间 设置时区 springboot 全局日志_全局日志_03