Java-SpringBoot注解方式实现AOP
AOP基本总结
- 连接点(JoinPoint):
- 连接点是程序运行的某个阶段点,如方法调用、异常抛出等
- 切入点(Pointcut):
- 切入点是JoinPoint的集合
- 是程序中需要注入Advice的位置的集合,即Advice在什么条件下才能被触发
- 增强(Advisor):
- 增强是切入点Pointcut和Advice的综合体,即在连接点JoinPoint上执行的行为
- 通过JDK/CGLIB代理模式实现AOP
- 切面(Aspect):
- @Aspect通常是一个类的注解,通常与@Component搭配使用
- AOP代理(AOP Proxy):
- AOP使用动态代理模式创建对象,从而实现在连接点JoinPoint处插入增强
- 其中JDK只能代理接口,CGLIB基于子类但不能代理final类
常用方法
| 方法 | 描述 |
| Object[] getArgs | 返回目标方法的参数数组 |
| Signature getSignature | 返回目标方法所在类信息 |
| Object getTarget | 返回被织入增强处理的目标对象 |
| Object getThis |
返回AOP代理对象 |
| Object proceed(Object[] args) |
利用反射执行目标方法并返回结果 |
增强类型
- @Before:前置增强,在某个JoinPoint执行前的增强
- @After:final增强,不管抛异常还是正常退出都执行的增强
- @AfterReturning:后置增强,方法正常退出时执行
- @AfterThrowing:异常抛出增强,抛出异常后执行
- @Around:环绕增强,包围一个连接点的增强,最强大的一个方式,且常用
示例说明
学了一下AOP的使用,写了个@Around的demo,将几个查询操作存入数据库作为Log并且定时清理过期数据
1)UserLog实体类
1 @Data
2 @ToString
3 @NoArgsConstructor
4 @AllArgsConstructor
5 public class UserLog implements Serializable {
6 private Integer id;
7 private String methodName;
8 private String methodArgs;
9 private String classFullName;
10 private String className;
11 private Date invokeTime;
12 private Double costTime;
13 }
2)LogTaskMapper对应mapper接口
1 public interface LogTaskMapper {
2 /**
3 * TEST AOP INSERT INFO INTO TABLE
4 * @param userLog
5 */
6 void insertUserLog(UserLog userLog);
7
8 /**
9 * DELETE LOGS IN TABLE LAST 2 DAYS
10 * @param minutes
11 */
12 void deleteUserLog(int minutes);
13 }
3)UserAopTask接口
1 public interface UserAopTask {
2 void insertUserLog(UserLog log);
3 }
4)UserAopTaskImpl实现类
1 @Component
2 public class UserAopTaskImpl implements UserAopTask {
3
4 private static final Logger logger = LoggerFactory.getLogger(UserAopTask.class);
5
6 @Autowired
7 private LogTaskMapper logTaskMapper;
8
9 private ExecutorService logHandler = Executors.newFixedThreadPool(1);//采用线程池复用一个线程执行
10
11 private static final int MINUTES_LOG_RETAIN = 30;//数据库中数据保留时间
12
13
14 @Override
15 public void insertUserLog(UserLog log) {
16 logHandler.submit(new logSubmitTask(log));
17 }
18
19 //内部类
20 class logSubmitTask implements Runnable{
21
22 private UserLog userLog;
23
24 public logSubmitTask(UserLog userLog){
25 this.userLog = userLog;
26 }
27
28 @Override
29 public void run() {
30 logTaskMapper.insertUserLog(userLog);
31 }
32 }
33
34 //定时清理任务
35 @Scheduled(cron = "0 30 * * * *")
36 public void scheduledDeleteLog(){
37 logger.info("开始清除[{}]分钟之前的图表查询日志...", MINUTES_LOG_RETAIN);
38 logTaskMapper.deleteUserLog(-1 * MINUTES_LOG_RETAIN);
39 }
40
41 }
5)TestUserAop切面类
1 @Aspect//切面
2 @Component//Spring容器管理
3 public class TestUserAop {
4 private static final Logger logger = LoggerFactory.getLogger(TestUserAop.class);
5
6 @Autowired
7 private UserAopTask userAopTask;
8 //使用环绕增强,第一参数必须是ProceedingJoinPoint
9 @Around(value = "@annotation(annotation)")//和注解类参数名保持一致
10 public Object aroundUserInfo(ProceedingJoinPoint pjp, TestUserAnnotation annotation) throws Throwable{
11 UserLog userLog = new UserLog();
12
13 System.out.println("=====================ANNOTATION BEGIN=====================");
14
15 Date date = new Date();
16 Long methodStart = date.getTime();//timestamp
17 System.out.println("ANNOTATION 开始耗时统计: "+ date);
18
19 userLog.setInvokeTime(date);
20
21 Object[] argsObj = pjp.getArgs();
22 Object res = pjp.proceed(argsObj);//利用反射调用目标方法
23
24 Long methodCost = System.currentTimeMillis() - methodStart;
25 double cost = methodCost/1000d;//timestamp 转换为 seconds
26
27 System.out.println("ANNOTATION 调用方法总耗时: "+ String.format("%.3f",cost) +" s");//保留3位小数
28 System.out.println("ANNOTATION 调用方法: "+annotation.methodName());//目标方法
29 System.out.println("ANNOTATION 调用方法参数: "+ new Integer((Integer) argsObj[0]));//我的参数就1个或者无参
30 System.out.println("ANNOTATION 调用类: "+pjp.getSignature().getDeclaringTypeName());//全类名
31 System.out.println("ANNOTATION 调用类名: "+pjp.getSignature().getDeclaringType().getSimpleName());//类名
32 System.out.println("ANNOTATION 调用结果: "+ JSON.toJSON(res));
33 System.out.println("=====================ANNOTATION FINISHED=====================");
34
35 userLog.setCostTime(Double.parseDouble(String.format("%.3f",cost)));
36 userLog.setClassFullName(pjp.getSignature().getDeclaringTypeName());
37 userLog.setClassName(pjp.getSignature().getDeclaringType().getSimpleName());
38 userLog.setMethodName(annotation.methodName());
39 userLog.setMethodArgs(Integer.toString(new Integer((Integer) argsObj[0])));
40
41 userAopTask.insertUserLog(userLog);
42
43 return res;
44
45 }
46 }
6)TestUserAnnotation注解类
我在service层写的AOP demo,对目标方法使用注解,注解名为注解类名即可,如@TestUserAnnotation
1 @Retention(RetentionPolicy.RUNTIME)//运行时有效
2 @Target(ElementType.METHOD)//作用于方法
3 @Documented
4 public @interface TestUserAnnotation {
5 String methodName() default "";//方法名,默认为空字符串
6 }
Java-SpringBoot注解方式实现AOP的更多相关文章
- Java SpringBoot注解方式开启异步支持
package task.demo.controller; import org.springframework.beans.factory.annotation.Autowired; import ...
- 基于AspectJ的注解方式进行AOP开发
-------------------siwuxie095 基于 AspectJ 的注解方式进行 AOP 开发 ...
- (转)使用Spring的注解方式实现AOP入门
http://blog.csdn.net/yerenyuan_pku/article/details/52865330 首先在Eclipse中新建一个普通的Java Project,名称为spring ...
- Spring系列之aAOP AOP是什么?+xml方式实现aop+注解方式实现aop
Spring系列之aop aop是什么?+xml方式实现aop+注解方式实现aop 什么是AOP? AOP为Aspect Oriented Programming 的缩写,意识为面向切面的编程,是通过 ...
- JAVA配置&注解方式搭建简单的SpringMVC前后台交互系统
前面两篇文章介绍了 基于XML方式搭建SpringMVC前后台交互系统的方法,博文链接如下: http://www.cnblogs.com/hunterCecil/p/8252060.html htt ...
- (转)使用Spring的注解方式实现AOP的细节
http://blog.csdn.net/yerenyuan_pku/article/details/52879669 前面我们已经入门使用Spring的注解方式实现AOP了,现在我们再来学习使用Sp ...
- 使用注解方式实现 AOP和IoC
使用注解方式实现AOP和IoC IOC和DI的注解 IOC: @Component:实现Bean组件的定义 @Repository:用于标注DAO类,功能与@Component作用相当 @Servic ...
- spring 纯注解方式 与AOP
spring注解方式 以前我也使用过纯注解方式.现在在这里做个记录 我们先认识几个我们都耳熟能详的注解 @configuration :从spring3.0这个注解就可以用于定义配置类,可以替换xml ...
- spring----IOC注解方式以及AOP
技术分析之Spring框架的IOC功能之注解的方式 Spring框架的IOC之注解方式的快速入门 1. 步骤一:导入注解开发所有需要的jar包 * 引入IOC容器必须的6个jar包 * 多引入一个:S ...
- Spring的注解方式实现AOP
Spring对AOP的实现提供了很好的支持.下面我们就使用Spring的注解来完成AOP做一个例子. 首先,为了使用Spring的AOP注解功能,必须导入如下几个包.aspectjrt.jar,asp ...
随机推荐
- 精尽Spring Boot源码分析 - 日志系统
该系列文章是笔者在学习 Spring Boot 过程中总结下来的,里面涉及到相关源码,可能对读者不太友好,请结合我的源码注释 Spring Boot 源码分析 GitHub 地址 进行阅读 Sprin ...
- POJ 1279 Art Gallery 半平面交 多边形的核
题意:求多边形的核的面积 套模板即可 #include <iostream> #include <cstdio> #include <cmath> #define ...
- 前端 | Vue 路由返回恢复页面状态
需求场景:首页搜索内容,点击跳转至详情页,页面后退返回主页,保留搜索结果. 方案:路由参数:路由守卫 需求描述 在使用 Vue 开发前端的时候遇到一个场景:在首页进行一些数据搜索,点击搜索结果进入详情 ...
- Hadoop知识总结
------------恢复内容开始------------ Hadoop知识点 Hadoop知识点什么是HadoopHadoop和Spark差异Hadoop常见版本,有哪些特点,一般是如何进行选择H ...
- java基础---设计模式(2)
结构型模式 出处:https://blog.csdn.net/zhangerqing/article/details/8239539 一.适配器模式 适配器模式将某个类的接口转换成客户端期望的另一个接 ...
- C++ 标准模板库(STL)——迭代器(iterators)的用法及理解
C++ STL中迭代器(iterators)用于遍历对象集合的元素.由于容器大小随着插入删除等操作动态改变,无法像静态数组那样获取数组长度然后遍历容器里的所有元素:这时就需要迭代器,每次从容器内第一个 ...
- TOSCA自动化测试工具
TOSCA由德国公司Tricentis研发,提供英文和德语两种版本. 目前他们的网上培训课程大约是2000一套,从初级到高级,从工程师到BA,有技术,也有测试管理. TOSCA的思想是,不用会编程的测 ...
- Serverless与Web后端天生不合?
Serverless/Faas/BaaS 等概念在这几年的技术圈中是绝对的热点词汇之一,国内外众多云厂商也纷纷推出自家的 Serverless 和函数计算产品,微信也依托腾讯云推出了基于 Server ...
- SVN教程(包括小乌龟) 全图解
转载自http://www.cnblogs.com/armyfai/p/3985660.html SVN使用教程总结 SVN简介: 为什么要使用SVN? 程序员在编写程序的过程中,每个程序员都会生成很 ...
- Linux虚拟机扩展磁盘
Linux虚拟机扩展磁盘 1.虚拟机关机,Vmware中扩展磁盘 2.虚拟机开机,查看磁盘大小 [root@hadoop6 ~]# df -h 文件系统 容量 已用 可用 已用% 挂载点 devtmp ...