SpringBoot 使用AOP功能

x33g5p2x  于2021-12-01 转载在 Spring  
字(2.9k)|赞(0)|评价(0)|浏览(384)

RPC,AOP都会用到代理,代理的技术有jdk的Proxy代理(必须实现接口),cglib(可以不实现接口,直接实现类),Javassist(jboss )而Spring boot本身也在方方面面使用了代理技术,在Spring中有两种动态代理方式,分别为jdk动态代理和CGLIB动态代理。

下面主要讲述,springboot如何使用AOP功能

1.POM文件中添加依赖

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

2.在application.properties中加入配置

spring.aop.auto=true

PS:其实springboot此配置是默认开启的,所以根本可以不用管了,在Springboot中使用过注解配置方式的人会问是否需要在程序主类中增加@EnableAspectJAutoProxy来启用,实际并不需要。看下面关于AOP的默认配置属性,其中spring.aop.auto属性默认是开启的,也就是说只要引入了AOP依赖后,其实默认已经增加了@EnableAspectJAutoProxy

# AOP
spring.aop.auto=true # Add @EnableAspectJAutoProxy. spring.aop.proxy-target-class=false # Whether subclass-based (CGLIB) proxies are to be created (true)
此处是设置是否开启CGLIB代理,默认不开启,相当于spring xml中
<aop:aspectj-autoproxy proxy-target-class="true"/>,
不过后面会有点奇怪的问题,springboot中,不管这个项是否设置为true或者false,都不会跟以前spring项目中,
如果没有设置为true,当代理类没有继承接口,启动项目的时候会报错。而springboot项目中,会自动转换成使用
CGLIB进行动态代理,其中原理是怎么实现,就没有去看底层代码了,估计底层进行了改造吧!

3.利用注解方式,实现AOP实现类。

import java.util.Arrays;
 
import javax.servlet.http.HttpServletRequest;
 
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;
 
@Aspect
@Component
public class WebLogAspect {
 
    private Logger logger = LoggerFactory.getLogger(WebLogAspect.class);
 
    @Pointcut("execution(public * com.springboot.test.controller.*.*(..))")
    public void webLog(){
    	System.out.println("begin");
    }
 
    @Before("webLog()")
    public void doBefore(JoinPoint joinPoint) throws Throwable {
        // 接收到请求,记录请求内容
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
 
        // 记录下请求内容
        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()));
 
    }
 
    @AfterReturning(returning = "ret", pointcut = "webLog()")
    public void doAfterReturning(Object ret) throws Throwable {
        // 处理完请求,返回内容
        logger.info("RESPONSE : " + ret);
    }
 
}

测试:

情况1:spring.aop.proxy-target-class=false,实现类没有继承接口。

上图可以说明使用了CGLIB动态代理。这里就可以看出,spring.aop.proxy-target-class好像并没有其效果,这个我都没有去深究了。有谁知道的,请留言一下咯!

情况2:spring.aop.proxy-target-class=false,实现类继承了接口。

上图可以看出使用了jdk动态代理!

情况3:spring.aop.proxy-target-class=true,实现类继承了接口。

上图可以看出使用了CGLIB动态代理。这里就可以看出,spring.aop.proxy-target-class起效果了。

结论:就是不太清楚情况一,为什么不会报错,知道的牛人,可以留言喔!

相关文章