017-Spring Boot AOP
一、概述
面向切面编程,将业务代码与处理琐碎相关度少的代码隔离开。以便达到重用,解耦。
用途:日志记录、权限处理、性能统计、监控、事务处理、异常处理等
通知类型有:前置通知、后置最终通知、后置返回通知、后置异常通知、环绕通知,
二、使用
1》增加POM依赖,默认已经启用aop,不需要增加注解等
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
2》创建一个Aspect切面类,并指定切点::
封装横切关注点(日志,监控等),需要配置通知(前置通知,后置通知)和切入点(那些包哪些类的哪些方法等)
@Aspect
@Component
public class LogAspect {
// 配置了com.lhx.spring.springboot.dao包及其子包下的所有类的所有方法
@Before("execution (* com.lhx.spring.springboot.dao..*.*(..))")
public void executeService() {
System.out.println("method executeService done");
}
}
2.1》前置通知 Before
/**
* 前置通知,方法调用前被调用
* @param joinPoint
*/
@Before("executeService()")
public void doBeforeAdvice(JoinPoint joinPoint){
System.out.println("我是前置通知!!!");
//获取目标方法的参数信息
Object[] obj = joinPoint.getArgs();
//AOP代理类的信息
joinPoint.getThis();
//代理的目标对象
joinPoint.getTarget();
//用的最多 通知的签名
Signature signature = joinPoint.getSignature();
//代理的是哪一个方法
System.out.println(signature.getName());
//AOP代理类的名字
System.out.println(signature.getDeclaringTypeName());
//AOP代理类的类(class)信息
signature.getDeclaringType();
//获取RequestAttributes
RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
//从获取RequestAttributes中获取HttpServletRequest的信息
HttpServletRequest request = (HttpServletRequest) requestAttributes.resolveReference(RequestAttributes.REFERENCE_REQUEST);
//如果要获取Session信息的话,可以这样写:
//HttpSession session = (HttpSession) requestAttributes.resolveReference(RequestAttributes.REFERENCE_SESSION);
Enumeration<String> enumeration = request.getParameterNames();
Map<String,String> parameterMap = Maps.newHashMap();
while (enumeration.hasMoreElements()){
String parameter = enumeration.nextElement();
parameterMap.put(parameter,request.getParameter(parameter));
}
String str = JSON.toJSONString(parameterMap);
if(obj.length > 0) {
System.out.println("请求的参数信息为:"+str);
}
}
注意:这里用到了JoinPoint和RequestContextHolder。通过JoinPoint可以获得通知的签名信息,如目标方法名、目标方法参数信息等。通过RequestContextHolder来获取请求信息,Session信息。
2.2》后置返回通知
/**
* 后置返回通知
* 这里需要注意的是:
* 如果参数中的第一个参数为JoinPoint,则第二个参数为返回值的信息
* 如果参数中的第一个参数不为JoinPoint,则第一个参数为returning中对应的参数
* returning 限定了只有目标方法返回值与通知方法相应参数类型时才能执行后置返回通知,否则不执行,对于returning对应的通知方法参数为Object类型将匹配任何目标返回值
* @param joinPoint
* @param keys
*/
@AfterReturning(value = "execution(* com.lhx.spring.springboot.dao..*.*(..))",returning = "keys")
public void doAfterReturningAdvice1(JoinPoint joinPoint,Object keys){
System.out.println("第一个后置返回通知的返回值:"+keys);
} @AfterReturning(value = "execution(* com.lhx.spring.springboot.dao..*.*(..))",returning = "keys",argNames = "keys")
public void doAfterReturningAdvice2(String keys){
System.out.println("第二个后置返回通知的返回值:"+keys);
}
调用方法
public String testAfterReturning(String key){
return "key=: "+key;
}
public Integer testAfterReturning01(Integer key){
return key;
}
当入参key=testsss时
第一个后置返回通知的返回值:key=: testsss
第二个后置返回通知的返回值:key=: testsss
当入参key=55553时
第一个后置返回通知的返回值:55553
2.3》后置异常通知
/**
* 后置异常通知
* 定义一个名字,该名字用于匹配通知实现方法的一个参数名,当目标方法抛出异常返回后,将把目标方法抛出的异常传给通知方法;
* throwing 限定了只有目标方法抛出的异常与通知方法相应参数异常类型时才能执行后置异常通知,否则不执行,
* 对于throwing对应的通知方法参数为Throwable类型将匹配任何异常。
* @param joinPoint
* @param exception
*/
@AfterThrowing(value = "executeService()",throwing = "exception")
public void doAfterThrowingAdvice(JoinPoint joinPoint,Throwable exception){
//目标方法名:
System.out.println(joinPoint.getSignature().getName());
if(exception instanceof NullPointerException){
System.out.println("发生了空指针异常!!!!!");
}
}
2.4》后置最终通知
/**
* 后置最终通知(目标方法只要执行完了就会执行后置通知方法)
* @param joinPoint
*/
@After("executeService()")
public void doAfterAdvice(JoinPoint joinPoint){ System.out.println("后置通知执行了!!!!");
}
2.5》环绕通知
/**
* 环绕通知:
* 环绕通知非常强大,可以决定目标方法是否执行,什么时候执行,执行时是否需要替换方法参数,执行完毕是否需要替换返回值。
* 环绕通知第一个参数必须是org.aspectj.lang.ProceedingJoinPoint类型
*/
@Around("executeService()")
public Object doAroundAdvice(ProceedingJoinPoint proceedingJoinPoint){
System.out.println("环绕通知的目标方法名:"+proceedingJoinPoint.getSignature().getName());
try {
Object obj = proceedingJoinPoint.proceed();
return obj;
} catch (Throwable throwable) {
throwable.printStackTrace();
}
return null;
}
三、AOP配置项
打开spring-boot-autoconfigure-1.5.9.RELEASE.jar查看包org.springframework.boot.autoconfigure.aop。AopAutoConfiguration
配置项:spring.aop.auto
@ConditionalOnProperty(prefix = "spring.aop", name = "auto", havingValue = "true", matchIfMissing = true)
spring.aop.auto=true【默认】含义:启用aop
配置项:spring.aop.auto.proxy-target-class
@ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "false", matchIfMissing = true)
spring.aop.auto.proxy-target-class=false【默认】,含义:启用JdkDynamicAutoProxyConfiguration动态代理,代理接口,不能代理类
注意如果代理的是类会自动切换至CglibAutoProxyConfiguration代理
spring.aop.auto.proxy-target-class=true,含义:启用CglibAutoProxyConfiguration动态代理,代理接口和类
四、配置参数
1、默认也提供了:@EnableAspectJAutoProxy注解
有两个参数:代理方式:proxyTargetClass 默认false,与上文一致
exposeProxy:获取代理后对象,默认false。不支持。如果是true,可以通过AopContext.currentProxy()获取
2、后置注解增加参数
@Before("execution (* com.lhx.spring.springboot.dao..*.*(..))")
public void logAfter(JoinPoint point) {
System.out.println("after log done," + point.getTarget().getClass()
+ ",args=" + Arrays.asList(point.getArgs())
+",method="+point.getSignature());
}
017-Spring Boot AOP的更多相关文章
- Spring Boot AOP解析
Spring Boot AOP 面向切面编程(AOP)通过提供另一种思考程序结构的方式来补充面向对象编程(OOP). OOP中模块化的关键单元是类,而在AOP中,模块化单元是方面. AOP(Aspec ...
- Spring Boot AOP之对请求的参数入参与返回结果进行拦截处理
Spring Boot AOP之对请求的参数入参与返回结果进行拦截处理 本文链接:https://blog.csdn.net/puhaiyang/article/details/78146620 ...
- 玩转spring boot——AOP与表单验证
AOP在大多数的情况下的应用场景是:日志和验证.至于AOP的理论知识我就不做赘述.而AOP的通知类型有好几种,今天的例子我只选一个有代表意义的“环绕通知”来演示. 一.AOP入门 修改“pom.xml ...
- Spring Boot - AOP(面向切面)
AOP 全称 Aspect Oriented Programming(面向切面),AOP主要实现的目的是针对业务处理过程中的切面进行提取,它所面对的是处理过程中的某个步骤或阶段,以获得逻辑过程中各部分 ...
- spring boot aop打印http请求回复日志包含请求体
一.引入依赖 <dependency> <groupId>org.springframework.boot</groupId> <artifactId> ...
- Spring boot AOP 记录请求日志
如何将所有的通过url的请求参数以及返回结果都输出到日志中? 如果在controller的类中每个方法名都写一个log输出肯定是不明智的选择. 使用spring的AOP功能即可完成. 1. 在pom. ...
- redis分布式锁-spring boot aop+自定义注解实现分布式锁
接这这一篇redis分布式锁-java实现末尾,实现aop+自定义注解 实现分布式锁 1.为什么需要 声明式的分布式锁 编程式分布式锁每次实现都要单独实现,但业务量大功能复杂时,使用编程式分布式锁无疑 ...
- Spring Boot AOP 扫盲,实现接口访问的统一日志记录
AOP 是 Spring 体系中非常重要的两个概念之一(另外一个是 IoC),今天这篇文章就来带大家通过实战的方式,在编程猫 SpringBoot 项目中使用 AOP 技术为 controller 层 ...
- Spring Boot AOP
AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术.AOP是Spring框架中的一个重要内容,它通 ...
- Spring boot Aop 示例
需要的依赖 <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-aop -- ...
随机推荐
- cassandra的primary key, partition key, cluster key,
https://stackoverflow.com/questions/24949676/difference-between-partition-key-composite-key-and-clus ...
- objc_setAssociatedObject 使用(转)
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 ...
- springboot开启事务管理
spring中开启事务管理需要在xml配置文件中配置,springboot中采取java config的配置方式. 核心是@EnableTransactionManager注解,该注解即为开启事务管理 ...
- linux 一行一行的读取文件
#!/bin/bash #reading data from a file count= cat test1 | while read line do echo "Line $count: ...
- hibernate配置文件再写
hibernate配置文件主要用于配置数据库连接和hibernate运行时所需的各种属性,每个hibernate配置文件对应一个Configuration对象,hibernate的配置文件有两种格式, ...
- eclipse JavaEE版"javax.servlet.http.HttpServlet" was not found on the Java Build Path问题的解决办法
使用eclipse JavaEE 版,新建 Dynamic Web Project 项目.在项目里添加 JSP 文件,会在文件头部出现错误提示.提示语句为:The superclass "j ...
- 【spring boot】在spring boot下使用多线程
使用场景: 方法处理到某一步,需要将信息交给另一个线程去处理!! =================================================================== ...
- php基本语法之逻辑运算符
百度经验 | 百度知道 | 百度首页 | 登录 | 注册 新闻 网页 贴吧 知道 经验 音乐 图片 视频 地图 百科 文库 帮助 首页 分类 杂志 任务 签到 回享计划 商城 知道 百度经验 > ...
- jQuery CSS 操作函数
CSS 属性 描述 css() 设置或返回匹配元素的样式属性. height() 设置或返回匹配元素的高度. offset() 返回第一个匹配元素相对于文档的位置. offsetParent() 返回 ...
- c++通过类名动态创建对象
转载:http://www.seacha.com/article.php/knowledge/cbase/2013/0615/2154.html 主要思想:在每次创建类的过程中,通过各自类的辅助类(所 ...