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. 20、oralce中单引号和双引号的区别

    20.oralce中单引号和双引号的区别: 20.1.单引号和双引号oracle都支持,但是两者是有区别的: 20.2.双引号在 Oracle 中的作用: 1.双引号的作用是:假如建立对象的时候,对象 ...

  2. Gym 101334E dp

    分析: 这一题给出的遍历的点的序列,不是树的中序遍历,前序遍历,只要遇到一个节点就打印一个节点.关键点就在,这个序列的首字母和尾字母一定要相同,因为最终都会回到根节点,那么每一个子树也一样. 状态: ...

  3. AOF重写导致的Redis进程被kill

    Redis环境描述 服务器: 阿里云16GB服务器 Redis版本: 5.0.5 持久化方式: AOF 问题描述 阿里云环境,使用docker安装的单节点redis5.x,频繁出现redis进程被操作 ...

  4. Quartz:Quartz任务异常处理方式

    Quartz提供了二种解决方法 1 立即重新执行任务 2 立即停止所有相关这个任务的触发器 解决的方式是:在你的程序出错时,用Quartz提供的JobExecutionException类相关方法就能 ...

  5. 其他:Windows10安装自带的Linux

    1.首先我们要打开Windows功能 2.在这里把勾打上 3.然后打开 设置 --- 更新和安全 --- 针对开发人员 --- (选择)开发人员模式 --- 确定启动 就行了 4.打开PowerShe ...

  6. kong配置upstream实现简单的负载均衡

    目录 通过konga实现 1. 配置upstream 2. 配置Service发布 3. 配置Route,匹配规则 4. 验证结果 通过 Kong Admin API实现 1. 配置upstream ...

  7. python使用笔记15--操作Excel

    python操作Excel需要引入第三方模块 执行以下命令: pip install xlwt pip install xlrd pip install xlutils 1.写Excel 1 impo ...

  8. C++ 11 智能指针(shared_ptr)类成员函数详解

    C++ 11 模板库的 <memory> 头文件中定义的智能指针,即 shared_ptr 模板类,用来管理指针的存储,提供有限的内存回收函数,可同时与其他对象共享该管理功能. share ...

  9. 团队开发day04

    通过myurl.openConnection()连接一直连接失败,问题解决: 在一般的Java Web程序开发中,我们通常使用localhost或者127.0.0.1来访问本机的Web服务, 但是如果 ...

  10. 团队开发day03

    完成安卓的登录和注册界面的设计,进行服务器端的开发,设计javabean实体 映射,零售商 ,商品,品牌商,订单类的构建 遇到问题:安卓发起网络请求,客户端回应请求,数据处理设置. 使用传统的方法 / ...