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的更多相关文章

  1. Java SpringBoot注解方式开启异步支持

    package task.demo.controller; import org.springframework.beans.factory.annotation.Autowired; import ...

  2. 基于AspectJ的注解方式进行AOP开发

    -------------------siwuxie095                                     基于 AspectJ 的注解方式进行 AOP 开发         ...

  3. (转)使用Spring的注解方式实现AOP入门

    http://blog.csdn.net/yerenyuan_pku/article/details/52865330 首先在Eclipse中新建一个普通的Java Project,名称为spring ...

  4. Spring系列之aAOP AOP是什么?+xml方式实现aop+注解方式实现aop

    Spring系列之aop aop是什么?+xml方式实现aop+注解方式实现aop 什么是AOP? AOP为Aspect Oriented Programming 的缩写,意识为面向切面的编程,是通过 ...

  5. JAVA配置&注解方式搭建简单的SpringMVC前后台交互系统

    前面两篇文章介绍了 基于XML方式搭建SpringMVC前后台交互系统的方法,博文链接如下: http://www.cnblogs.com/hunterCecil/p/8252060.html htt ...

  6. (转)使用Spring的注解方式实现AOP的细节

    http://blog.csdn.net/yerenyuan_pku/article/details/52879669 前面我们已经入门使用Spring的注解方式实现AOP了,现在我们再来学习使用Sp ...

  7. 使用注解方式实现 AOP和IoC

    使用注解方式实现AOP和IoC IOC和DI的注解 IOC: @Component:实现Bean组件的定义 @Repository:用于标注DAO类,功能与@Component作用相当 @Servic ...

  8. spring 纯注解方式 与AOP

    spring注解方式 以前我也使用过纯注解方式.现在在这里做个记录 我们先认识几个我们都耳熟能详的注解 @configuration :从spring3.0这个注解就可以用于定义配置类,可以替换xml ...

  9. spring----IOC注解方式以及AOP

    技术分析之Spring框架的IOC功能之注解的方式 Spring框架的IOC之注解方式的快速入门 1. 步骤一:导入注解开发所有需要的jar包 * 引入IOC容器必须的6个jar包 * 多引入一个:S ...

  10. Spring的注解方式实现AOP

    Spring对AOP的实现提供了很好的支持.下面我们就使用Spring的注解来完成AOP做一个例子. 首先,为了使用Spring的AOP注解功能,必须导入如下几个包.aspectjrt.jar,asp ...

随机推荐

  1. POJ 2002 二分 计算几何

    根据正方形对角的两顶点求另外两个顶点公式: x2 = (x1+x3-y3+y1)/2; y2 = (x3-x1+y1+y3)/2; x4= (x1+x3+y3-y1)/2; y4 = (-x3+x1+ ...

  2. 37.qt quick- 高仿微信实现局域网聊天V3版本(添加登录界面、UDP校验登录、皮肤更换、3D旋转)

    1.版本介绍(已上传至群里) 版本说明: 添加登录界面. UDP校验登录. 皮肤更换. 3D旋转(主界面和登录界面之间切换) . 效果图如下所示: 如果效果图加载失败,可以去哔哩哔哩 https:// ...

  3. nginx反向代理tcp协议的80端口

    需求:内网有一台mqtt协议服务器,需要将外网的mqtt请求通过一台服务器代理到内网的mqtt服务器上.而这台代理服务器不会开放出了80之外的端口,所以只能使用80端口来转发mqtt请求. 步骤:1. ...

  4. IDA,IDA PRO 产品介绍

    IDA理念这是我们在开发产品时竭尽全力遵循的理念--在此过程中,我们相信我们将开发出能够为您带来所需的可靠性.便利性和易用性的软件.没有什么能打败人脑因为我们知道一秒钟的洞察力仍然胜过百年的处理时间, ...

  5. Macbook(M1版)的用户看过来,.net 6 Preview 6支持Apple Silicon for macOS

    本文由葡萄城技术团队翻译 转载请注明出处:葡萄城官网,葡萄城为开发者提供专业的开发工具.解决方案和服务,赋能开发者. 我们很高兴发布.NET6预览的第6版,本次预览是倒数第二次预览了.在本次预览发布之 ...

  6. Django基础010--ORM操作

    orm返回的数据有两种,QuerySet,object 1.QuerySet支持链式编程,可以在all()后面继续.方法 teachers = models.Teacher.objects.all() ...

  7. [刘阳Java]_Spring中IntrospectorCleanupListener的用途【补充】_第16讲

    这篇文章不是我自己原创的,但是为了后期的阅读,所以我收录网上的一篇文章.为了尊重作者的版权,转载地址先放上来,大家也可以去访问他的原始文章.http://jadyer.cn/2013/09/24/sp ...

  8. [善用佳软]Chrome插件之彩云小译

    最近公众号新推出个栏目[善用佳软],旨在和大家分享各种小插件和制作开源小软件. 最近在浏览外网时,发现一个贼好用的翻译神器---[彩云小译],在网页端就可以快速的对照翻译出来,经过试用发现无论是速度还 ...

  9. Scala学习——集合

    Scala集合 一.数组 package top.ruandb.scala.Course04 object ArrayApp { def main(args: Array[String]): Unit ...

  10. 随机数种子(random seed)

    在科学技术和机器学习等其他算法相关任务中,我们经常需要用到随机数,为了把握随机数的生成特性,从随机数的随机无序中获得确定和秩序.我们可以利用随机数种子(random seed)来实现这一目标,随机数种 ...