SpringBoot AOP概念及使用Demo
AOP核心概念
1、横切关注点
对哪些方法进行拦截,拦截后怎么处理,这些关注点称之为横切关注点
2、切面(aspect)-》(通知+切点)
类是对物体特征的抽象,切面就是对横切关注点的抽象。
通知+切点
意思就是所有要被应用到增强(advice)代码的地方。(包括方法的方位信息)
3、连接点(joinpoint)-》(被拦截的方法)
被拦截到的点,因为Spring只支持方法类型的连接点,所以在Spring中连接点指的就是被拦截的方法,实际上连接点还可以是字段或者构造器
4、切入点(pointcut)-》(描述拦截那些方法的部分)
对连接点进行拦截的定义
5、通知(advice)-》(拦截后执行自己业务逻辑的那些部分)
所谓通知指的就是指拦截到连接点之后要执行的代码,通知分为前置、后置、异常、最终、环绕通知五类
这玩意也叫 增强
在逻辑层次上包括了我们抽取的公共逻辑和方位信息。因为Spring只能方法级别的应用AOP,也就是我们常见的before,after,after-returning,after-throwing,around五种,意思就是在方法调用前后,异常时候执行我这段公共逻辑呗。
6、目标对象
代理的目标对象
7、织入(weave)
将切面应用到目标对象并导致代理对象创建的过程。
比如根据Advice中的方位信息在指定切点的方法前后,执行增强。这个过程Spring 替我们做好了。利用的是CGLIB动态代理技术。
8、引入(introduction)
在不修改代码的前提下,引入可以在运行期为类动态地添加一些方法或字段
图解
上面那一堆看不懂对吗? 我也不太懂。
来看张图
好了,现在我们直接看代码,简单的使用如下:
引入pom
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.9.8</version><!--$NO-MVN-MAN-VER$-->
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.2</version><!--$NO-MVN-MAN-VER$-->
</dependency> <!-- AspectJ -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.9.2</version><!--$NO-MVN-MAN-VER$-->
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.2</version><!--$NO-MVN-MAN-VER$-->
</dependency>
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>2.2.2</version>
</dependency> </dependencies>
创建DTO对象
package com.szl.demo.common.dto; import lombok.Data; @Data
public class AccountDto {
private String accountNo;
private String accountName;
private Double balance;
}
创建service和service实现类
package com.szl.demo.service; import com.szl.demo.common.dto.AccountDto; public interface DemoService { public AccountDto getUserAccount(); }
package com.szl.demo.service.impl; import org.springframework.stereotype.Service;
import com.szl.demo.common.dto.AccountDto;
import com.szl.demo.service.DemoService; @Service("demoService")
public class DemoServiceImpl implements DemoService { public AccountDto getUserAccount() {
AccountDto dto = new AccountDto();
dto.setAccountNo("22133232001");
dto.setAccountName("XXX");
dto.setBalance(3000D);
return dto;
}
}
创建controller
package com.szl.demo.controller; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import com.szl.demo.common.dto.AccountDto;
import com.szl.demo.service.DemoService; @Controller
public class DemoController {
@Autowired
private DemoService demoService;
/**
* @param request
* @param response
* @param body 这个是请求body体
* @param nickName 这个是post参数
* @param birthday 这个是post参数
* @return
*/
@ResponseBody
@RequestMapping(value = "/testAopDemo", method = RequestMethod.POST,
consumes = "application/json",
produces = "application/json;charset=UTF-8")
public AccountDto testAopDemo(HttpServletRequest request, HttpServletResponse response,
@RequestBody String body,
@RequestParam("nickName") String nickName,
@RequestParam("birthday") String birthday) {
log.info("controller层 请求body内容: " + body);
log.info("controller层 请求参数nickName内容: " + nickName);
log.info("controller层 请求参数birthday内容: " + birthday);
return demoService.getUserAccount();
} }
以上工作全部做完后,现在我们创建AOP核心代码块
package com.szl.demo.common.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.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import lombok.extern.slf4j.Slf4j; /**
* @author Jimmy Shan
* @desc 创建AOP 切面记录controller的日志记录
* @Slf4j 必须结合lombok一起使用,否则无效
*/
@Slf4j
@Aspect
@Component
public class WebLogAcpect {
// 用于记录每个controller执行的耗时时间,毫秒级
private ThreadLocal<Long> timeLocal = new ThreadLocal<>(); /**
* 定义切入点,切入点为com.example.aop下的所有函数
*/
@Pointcut("execution(public * com.szl.demo.controller.*.*(..))")
public void webLog(){} /**
* @param joinPoint
* @throws Throwable
* @desc 前置通知:在连接点之前执行的通知
*/ @Before("webLog()")
public void doBefore(JoinPoint joinPoint) throws Throwable {
long startTime = System.currentTimeMillis();
timeLocal.set(startTime);// 记录开始时间 // 接收到请求,记录请求内容
ServletRequestAttributes attributes = (ServletRequestAttributes)
RequestContextHolder.getRequestAttributes();
HttpServletRequest request = attributes.getRequest();
// 记录下请求内容
log.info("URL : " + request.getRequestURL().toString());
log.info("HTTP_METHOD : " + request.getMethod());
log.info("IP : " + request.getRemoteAddr());
log.info("CLASS_METHOD : " + joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName());
log.info("ARGS : " + Arrays.toString(joinPoint.getArgs()));
//获取请求参数信息 和 requestBody数据
List<String> paramList = new ArrayList<>();
Object[] objArr = joinPoint.getArgs();
for (int i = 0; i < objArr.length; i++) {
if (objArr[i] instanceof String) {
paramList.add(String.valueOf(objArr[i]));
}
}
log.info("AOP获取参数内容为: " + String.join("###", paramList));
} /**
* @param ret
* @throws Throwable
* @desc 处理完成请求,返回的信息
*/ @AfterReturning(returning = "ret", pointcut = "webLog()")
public void doAfterReturning(Object ret) throws Throwable {
log.info("返回的内容: " + ret);
log.info("耗时: {} 毫秒", (System.currentTimeMillis() - timeLocal.get().longValue()));
timeLocal.remove();
} }
OK,到此我们的AOP就可以正常的工作了,我们来看一下效果,控制台日志信息输出如下:
00:33:37.167 [http-nio-8081-exec-1] INFO - Initializing Spring DispatcherServlet 'dispatcherServlet'
00:33:37.167 [http-nio-8081-exec-1] INFO - Initializing Servlet 'dispatcherServlet'
00:33:37.171 [http-nio-8081-exec-1] INFO - Completed initialization in 2 ms
00:33:37.218 [http-nio-8081-exec-1] INFO - URL : http://127.0.0.1:8081/testAopDemo
00:33:37.218 [http-nio-8081-exec-1] INFO - HTTP_METHOD : POST
00:33:37.218 [http-nio-8081-exec-1] INFO - IP : 127.0.0.1
00:33:37.218 [http-nio-8081-exec-1] INFO - CLASS_METHOD : com.szl.demo.controller.DemoController.testAopDemo
00:33:37.218 [http-nio-8081-exec-1] INFO - ARGS : [org.apache.catalina.connector.RequestFacade@69bd93bb, org.apache.catalina.connector.ResponseFacade@5a33b12, {"info2":"haha", "name":"Jackson"}, 百里守约, 2019-06-05]
00:33:37.218 [http-nio-8081-exec-1] INFO - AOP获取参数内容为: {"info2":"haha", "name":"Jackson"}###百里守约###2019-06-05
00:33:37.234 [http-nio-8081-exec-1] INFO - controller层 请求body内容: {"info2":"haha", "name":"Jackson"}
00:33:37.234 [http-nio-8081-exec-1] INFO - controller层 请求参数nickName内容: 百里守约
00:33:37.234 [http-nio-8081-exec-1] INFO - controller层 请求参数birthday内容: 2019-06-05
00:33:37.234 [http-nio-8081-exec-1] INFO - 返回的内容: AccountDto(accountNo=22133232001, accountName=XXX, balance=3000.0)
00:33:37.234 [http-nio-8081-exec-1] INFO - 耗时: 16 毫秒
蓝色字体部分就是 AOP 和 controller 获取参数的值信息。
转自:https://www.cnblogs.com/lic309/p/4079194.html
https://blog.csdn.net/lmb55/article/details/82470388
SpringBoot AOP概念及使用Demo的更多相关文章
- springboot(整合多数据源demo,aop,定时任务,异步方法调用,以及获取properties中自定义的变量值)
有这么一个需求 每个部门,需要操作的数据库不同,A部门要将数据放test数据库,B 部门数据 要放在test1数据库 同一个项目 需要整合 多个数据源 上传个demo 方便自己以后回看!!!!!!!! ...
- spring-boot+mybatisPlus+shiro的集成demo 我用了5天
spring-boot + mybatis-plus + shiro 的集成demo我用了五天 关于shiro框架,我还是从飞机哪里听来的,就连小贱都知道,可我母鸡啊.简单百度了下,结论很好上手,比s ...
- Spring 3 AOP 概念及完整示例
AOP概念 AOP(Aspect Oriented Programming),即面向切面编程(也叫面向方面编程,面向方法编程).其主要作用是,在不修改源代码的情况下给某个或者一组操作添加额外的功能.像 ...
- springboot+aop切点记录请求和响应信息
本篇主要分享的是springboot中结合aop方式来记录请求参数和响应的数据信息:这里主要讲解两种切入点方式,一种方法切入,一种注解切入:首先创建个springboot测试工程并通过maven添加如 ...
- SpringBoot+AOP整合
SpringBoot+AOP整合 https://blog.csdn.net/lmb55/article/details/82470388 https://www.cnblogs.com/onlyma ...
- springboot aop 不生效原因解决
最近参照资料创建Springboot AOP ,结果运行后aop死活不生效. 查明原因: 是我在创建AOP类时选择了Aspect类型,创建后才把这个文件改为Class类型,导致一直不生效, 代码配置这 ...
- springboot aop 自定义注解方式实现完善日志记录(完整源码)
版权声明:本文为博主原创文章,欢迎转载,转载请注明作者.原文超链接 一:功能简介 本文主要记录如何使用aop切面的方式来实现日志记录功能. 主要记录的信息有: 操作人,方法名,参数,运行时间,操作类型 ...
- springboot aop 自定义注解方式实现一套完善的日志记录(完整源码)
https://www.cnblogs.com/wenjunwei/p/9639909.html https://blog.csdn.net/tyrant_800/article/details/78 ...
- springBoot AOP学习(一)
AOP学习(一) 1.简介 AOp:面向切面编程,相对于OOP面向对象编程. Spring的AOP的存在目的是为了解耦.AOP可以让一切类共享相同的行为.在OOP中只能通过继承类或者实现接口,使代码的 ...
随机推荐
- win 10 关闭或打开 测试模式
一.关闭测试模式 方法: 以管理员身份运行 cmd 运行:bcdedit /set testsigning off 重启电脑 二.开启测试模式 以管理员身份运行 cmd 运行:bcdedit /set ...
- how-does-mysql-replication-really-work/ what-causes-replication-lag
https://www.cnblogs.com/kevingrace/p/6274073.html https://www.cnblogs.com/kevingrace/p/6261091.html ...
- springboot 整合OSS
OSS 阿里云对象存储服务(Object Storage Service,简称 OSS),是阿里云提供的海量.安全.低成本.高可靠的云存储服务.OSS可用于图片.音视频.日志等海量文件的存储.各种终端 ...
- docker基本排错
遇到了一个很奇葩的问题,docker运行一个容器后,执行docker ps -a可以查看到该容器处于运行状态,但是无法进入该容器. 试着使用docker stop ID和docker kill -s ...
- 七、spring生命周期之初始化和销毁方法
一.通过@Bean指定初始化和销毁方法 在以往的xml中,我们是这样配置的 <bean id="exampleInitBean" class="examples.E ...
- TP5 模型CURD
ThinkPHP5的模型是一种对象-关系映射(Object / Relation Mapping ,简称 ORM)的封装,并且提供了简洁的ActiveRecord实现.一般来说,每个数据表会和一个“模 ...
- Connection to api@localhost failed. [08001] Could not create connection to d
pycharm 换成2019之后连接数据库用户名密码数据库名字都没错,就是连接不上去,网上百度一下,试试将URL后面拼接 ?useSSL=false&serverTimezone=UTC 发现 ...
- python中将已有链接的视频进行下载
使用python爬取视频网站时,会得到一系列的视频链接,比如MP4文件.得到视频文件之后需要对视频进行下载,本文写出下载视频文件的函数. 首先导入requests库,安装库使用pip install ...
- 19 IO流(十六)——Commons工具包,FileUtils(一)
Commons包的API:自己查吧懒得传云 Commons包的导入方法 Commons是一个java的IO开源工具,导入方法: 从apache.org下载commons包 解压 copy其中的comm ...
- leetcode整数反转
给出一个 32 位的有符号整数,你需要将这个整数中每位上的数字进行反转. 示例 1: 输入: 123输出: 321 示例 2: 输入: -123输出: -321 示例 3: 输入: 120输出: 21 ...