SpringBoot 使用AOP功能
2018-07-11 14:26
441 查看
RPC,AOP都会用到代理,代理的技术有jdk的Proxy代理(必须实现接口),cglib(可以不实现接口,直接实现类),Javassist(jboss )而Spring boot本身也在方方面面使用了代理技术,在Spring中有两种动态代理方式,分别为jdk动态代理和CGLIB动态代理。
两者主要区别:
1:jdk代理的目标对象必须实现若干接口,因为有接口,所以使系统更加松耦合。
而CGLIB代理就跟jdk代理刚刚相反目标对象没有实现任何接口,spring使用CGLIB库生成目标对象的子类,代理类与目标类是继承关系,所以耦合性没有使用JDK的动态代理好。
2.:JDK动态代理(使用Java反射机制生成代理对象)Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(),this),CGLIB动态代理使用Enhancer基于继承的方式,
底层采用ASM字节码生成框架,使用字节码技术生成代理类,比使用Java反射效率要高。
两者主要区别:
1:jdk代理的目标对象必须实现若干接口,因为有接口,所以使系统更加松耦合。
而CGLIB代理就跟jdk代理刚刚相反目标对象没有实现任何接口,spring使用CGLIB库生成目标对象的子类,代理类与目标类是继承关系,所以耦合性没有使用JDK的动态代理好。
2.:JDK动态代理(使用Java反射机制生成代理对象)Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(),this),CGLIB动态代理使用Enhancer基于继承的方式,
底层采用ASM字节码生成框架,使用字节码技术生成代理类,比使用Java反射效率要高。
下面主要讲述,springboot如何使用AOP功能
1.POM文件中添加依赖
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId> </dependency>2.在application.properties中加入配置
spring.aop.auto=truePS:其实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起效果了。
结论:就是不太清楚情况一,为什么不会报错,知道的牛人,可以留言喔!
稿毕!!!!!!
相关文章推荐
- Spring AOP进行日志记录,管理 (使用Spring的拦截器功能获取对action中每个方法的调用情况,在方法调用前和调用后记录相关日志。)
- 使用Spring AOP添加统计时间的功能
- Springboot 使用 JSR 303 对 Controller 控制层校验及 Service 服务层 AOP 校验 使用消息资源文件对消息国际化
- 不使用spring的aop功能实现日志输出
- Spring boot中使用aop详解
- Spring Boot 使用 AOP 实现页面自适应
- Spring Boot教程(六)使用AOP统一处理Web请求日志
- spring boot集成velocity及使用layout和2.X的toolbox功能
- spring boot 添加aop功能
- ITCAST视频-Spring学习笔记(使用CGLIB实现AOP功能与AOP概念解释)
- spring boot aop的使用
- (二)SpringBoot之springboot开发工具的使用以及springboot插件的功能
- 使用 Spring Boot 2.0 + WebFlux 实现 RESTful API功能
- Spring Boot中使用AOP统一处理Web请求日志
- springboot【19】日志管理之使用AOP统一处理Web请求日志
- 使用springBoot的拦截器功能介绍
- SpringBoot中aop的使用
- SpringBoot中使用AOP 监控sql耗时
- spring-boot之aop使用
- Spring Boot 使用AOP切换多数据源时,被@Transactional注解的方法会抛异常