springboot:AOP 切面编程

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/weixin_38750084/article/details/88738777

说起spring,我们知道其最核心的两个功能就是AOP(面向切面)和IOC(控制反转),这边文章来总结一下SpringBoot如何整合使用AOP。

一、示例应用场景:对所有的web请求做切面来记录日志。

1、pom中引入SpringBoot的web模块和使用AOP相关的依赖:

<dependency>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- 引入AOP依赖start-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>

        <!-- AspectJ -->
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjrt</artifactId>
            <version>1.6.11</version>
        </dependency>

        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.6.11</version>
        </dependency>

        <dependency>
            <groupId>cglib</groupId>
            <artifactId>cglib</artifactId>
            <version>2.1</version>
        </dependency>

其中: 
cglib包是用来动态代理用的,基于类的代理; 
aspectjrt和aspectjweaver是与aspectj相关的包,用来支持切面编程的; 
aspectjrt包是aspectj的runtime包; 
aspectjweaver是aspectj的织入包;

写个controller,路径在:

com.hy.bb.web.controller下面

3、定义切面类,实现web层的日志切面

要想把一个类变成切面类,需要两步, 
① 在类上使用 @Component 注解 把切面类加入到IOC容器中 
② 在类上使用 @Aspect 注解 使之成为切面类

package com.hy.bb.web.aop;

import org.aspectj.lang.JoinPoint;
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.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 WebLogAcpect {

    private Logger logger = LoggerFactory.getLogger(WebLogAcpect.class);

    /**
     * 定义切入点,切入点为com.hy.bb.web.controller下的所有函数
     */
    @Pointcut("execution(public * com.hy.bb.web.controller..*.*(..))")
    public void webLog(){}

    /**
     * 前置通知:在连接点之前执行的通知
     * @param joinPoint
     * @throws Throwable
     */
    @Before("webLog()")
    public void doBefore(JoinPoint joinPoint) throws Throwable {
        // 接收到请求,记录请求内容
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();

        System.out.println("============----------=========");
        // 记录下请求内容
        logger.info("URL : " + request.getRequestURL().toString());
        logger.info("HTTP_METHOD : " + request.getMethod());
        logger.info("IP : " + request.getRemoteAddr());
        logger.info("CLASS_METHOD : " +         
        joinPoint.getSignature().getDeclaringTypeName() + "." + 
        joinPoint.getSignature().getName());
        logger.info("ARGS : " + Arrays.toString(joinPoint.getArgs()));
        // 通知的签名
        Signature signature = joinPoint.getSignature();
        //AOP代理的类名和方法名
        logger.info("类名 :"+signature.getDeclaringTypeName()+"   "+" 方法名:"+signature.getName());
        System.out.println("============----------=========");

    }

    @AfterReturning(returning = "ret",pointcut = "webLog()")
    public void doAfterReturning(Object ret) throws Throwable {
        // 处理完请求,返回内容
        logger.info("RESPONSE : " + ret);
    }


}

execution详解: https://blog.csdn.net/kkdelta/article/details/7441829

以上的切面类通过 @Pointcut定义的切入点为com.hy.bb.web.controller 包下的所有函数做切人,通过 @Before实现切入点的前置通知,通过 @AfterReturning记录请求返回的对象。

测试:

参考:https://blog.csdn.net/lmb55/article/details/82470388

猜你喜欢

转载自blog.csdn.net/weixin_38750084/article/details/88738777
今日推荐