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. 关于asp.net中Repeater控件的一些应用

    在Asp.net中,我是比较喜欢用Repeater这个控件,刚刚遇到的一个问题,怎么实现单击 <asp:LinkButton>,通过后台的单击事件获取同一行数据中的其他数据(对象). 1, ...

  2. Redis主从,集群部署及迁移

    工作中有时会遇到需要把原Redis集群下线,迁移到另一个新的Redis集群的需求(如机房迁移,Redis上云等原因).此时原Redis中的数据需要如何操作才可顺利迁移到一个新的Redis集群呢? 本节 ...

  3. 利用C语言输出一个二元一次函数

    #include<stdio.h> #include<math.h> int main(void)//其实void我认为在这可有可无 {  double a,b,c,x1,x2 ...

  4. Vue Element-ui表单校验规则,你掌握了哪些?

    1.前言   Element-ui表单校验规则,使得错误提示可以直接在form-item下面显示,无需弹出框,因此还是很好用的.   我在做了登录页面的表单校验后,一度以为我已经很了解表单的校验规则. ...

  5. hive学习笔记之十一:UDTF

    欢迎访问我的GitHub https://github.com/zq2599/blog_demos 内容:所有原创文章分类汇总及配套源码,涉及Java.Docker.Kubernetes.DevOPS ...

  6. Mybatis学习(3)实现数据的增删改查

    前面已经讲到用接口的方式编程.这种方式,要注意的一个地方就是.在User.xml  的配置文件中,mapper namespace="com.yihaomen.mybatis.inter.I ...

  7. 关于mysql binlog二进制

    binlog 在mysql中,当发生数据变更时,都会将变更数据的语句,通过二进制形式,存储到binlog日志文件中. 通过binlog文件,你可以查看mysql一段时间内,对数据库的所有改动. 也可以 ...

  8. 公钥-私钥 白名单-黑名单 Linux 远程访问及控制(SSH)

    远程访问及控制一.SSH远程管理二.OpenSSH服务器① SSH (Secure Shell)协议② OpenSSH三.配置OpenSSH服务器举例四.sshd 服务支持两种验证方式五.使用SSH客 ...

  9. PYD应用方法

    1. 'ImportError: No module named xxx' 可能是xxx.pyd所在路径不在sys.path中. 解决方法:import之前用sys.path.append()方法加入 ...

  10. 学生信息管理系统--基于jsp技术和MySQL的简单增删改查

    web实现增删改查的方式有很多啊,对于初学者来说当然是要先了解各部分的传值的方式.本篇博客从jsp技术的最基础方面进行说明. 一.什么是jsp技术 首先,我们要了解什么是jsp技术. jsp技术是基于 ...