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. 利用C语言将混乱数字排序(即冒泡排序法)(含思路)

    大一C语言 你没学过吗 这篇可以称的上入门级别的c语言了 当然还有水仙花数,冒泡排序等经典的C语言程序 后面也会逐一更新 尽情期待喔~~~ 冒泡排序法的基本思路为:每次将相邻的两个数比较,将小的调在前 ...

  2. CentOS-配置YUM源加速(阿里云、Nexus3)

    备份本地源 mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.backup 配置CentOS6(aliyun ...

  3. Comparator的compare方法如何定义升序降序

    最近做算法题用了Comparator接口下的compare方法,思考了一下升序和降序的规则是如何来的,现在做一个补充,方便以后回顾.  升序代码 public static void main(Str ...

  4. python使用笔记21--发邮件

    发邮件需要第三方模块 pip install yamail 1 #import yagmail #--别人写的,发中文附件的时候是乱码 2 import yamail #牛牛基于yagmail改的 3 ...

  5. Jmeter使用笔记001

    Apache JMeter是一款纯java编写负载功能测试和性能测试开源工具软件. jmeter也可以用来做接口自动化 一.jmeter基础 1.1 jmeter的执行顺序 1,执行配置元件2,前置处 ...

  6. C语言:输出数字各个位的数字及和

    #include <stdio.h> int main() { char sh[13][5]={"个","十","百",&quo ...

  7. Spring boot+Mybatis+MySQL插入中文乱码

    转载:https://www.jianshu.com/p/bd0311a33c16 现象: 搭建spring boot+mybatis+mysql时出现插入mysql的中文出现乱码???.   mys ...

  8. [刘阳Java]_美团点评2018届校招面试总结_Java后台开发【转载】

    美团喜欢一口气把三轮技术面和HR面一起面完,虽然身心比较累(每一面差不多一个小时),不过也算是一个好事,不像某些公司一天就一面然后让回去等消息,等面试通知也等得让人很焦虑,而且还容易出现面试时间冲突. ...

  9. [刘阳Java]_SpringMVC访问静态资源_第9讲

    有些时候我们在使用SpringMVC的时候造成无法访问静态资源文件(如:html,js,css,image等等).其主要的原因出在web.xml文件我们设置SpringMVC前端控制器的映射路径 &l ...

  10. IO流 connect reset

    目录 出现场景 解决思路 出现场景 通过外部OBS下载10文件,然后通过工具将这10个文件打包成一个文件A.zip上传,最后将这个A.zip下载并解压,解压A.zip后发现文件数量不是10个. 解决思 ...