目录

  1. 1. 定义一个 aspect
  2. 2. 创建一个 around advice

在之前的读书笔记 Spring in Acton 4 读书笔记之 AOP 原理及 Spring 对 AOP 的支持 中,讲到 Spring 对 AOP 的支持包含四方面:

  1. Spring 基于代理的经典的 AOP
  2. 使用 XML 配置将纯 POJO 转化为 aspect
  3. 使用 Spring 的 @Aspect 标签,创建 aspect
  4. Spring 不创建 aspect,只注入(引用)AspectJ 框架的 aspect

Spring in Action(Spring 实战)的第四章第三节(4.3 Creating annotated aspects)讲述了其中第三种,即如何使用标签创建 aspect。本文讲解其中的前面两小节:定义 aspect 以及创建 around advice。

AspectJ 5 引进的主要特性是使用标签创建 aspect。AspectJ 5 的缺点是需要学习扩展的 java 语言。但是 AspectJ 面向标签的编程模式使得将一个类转换成 aspect 变得很容易,只需要在类中加一些标签。

定义一个 aspect

以下是使用标签创建 AOP 的例子,这个例子在之前的文章中有提到过,观众在演出开始前后,以及出问题时,会自动做出一些反应:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package concert;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
@Aspect
public class Audience {  @Before("execution(** concert.Performance.perform(..))")
  public void silenceCellPhones() {    System.out.println("Silencing cell phones");
  }
  @Before("execution(** concert.Performance.perform(..))")
  public void takeSeats() {    System.out.println("Taking seats");
  }
  @AfterReturning("execution(** concert.Performance.perform(..))")
   public void applause() {    System.out.println("CLAP CLAP CLAP!!!");
  }
  @AfterThrowing("execution(** concert.Performance.perform(..))")
   public void demandRefund() {    System.out.println("Demanding a refund");
  }
}

Audience 类上加上 @Aspect,用来表示 Audience 是一个 aspect,而 Audience 被标注的方法定义了具体的行为。在表演开始前,观众需要就座(takeSeats()),将手机静音(silenceCellPhones())。

表演结束后,观众需要鼓掌(applause()),如果表演过程中出现了异常,观众会要求退票(demandRefund())。AspectJ 提供了五个标签来定义 advice:

  • @After,在方法正常执行结束,或者出现异常的时候,执行 aspect。
  • @AfterReturning,在方法正常执行结束后,执行 aspect。
  • @AfterThrowing,在方法抛出异常的时候,执行 aspect。
  • @Around,在方法执行过程中,执行 aspect。
  • @Before, 在方法执行之前,执行 aspect。

上面的例子中,所有标签的值都是一个 pointcut 表达式,而且在这个例子里,正好是一样的(因为是作用在同一个方法上)。实际上,可以将这个 pointcut 定义好,然后进行引用,这样可以避免重复编写 pointcut。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
@Aspect
public class Audience {  @Pointcut("execution(** concert.Performance.perform(..))")
  public void performance() {}

  @Before("performance()")
  public void silenceCellPhones() {    System.out.println("Silencing cell phones");
  }
  @Before("performance()")
  public void takeSeats() {    System.out.println("Taking seats");
  }
  @AfterReturning("performance()")
  public void applause() {    System.out.println("CLAP CLAP CLAP!!!");
  }
  @AfterThrowing("performance()")
  public void demandRefund() {    System.out.println("Demanding a refund");
  }
}

上面的代码,使用 @Pointcut 标签对 performance()方法进行标注,这样,就可以直接使用 performance()来代替 pointcut 表达式了。performance()只是一个标记,所以方法体可以也必须是空的。

如果只是定义了上面 Audience 这个 aspect, 那么其实什么也做不了。必须有一个配置文件,指出它是一个 aspect,并且解析这些标签,然后创建代理,最终将 Audience 转化为一个 aspect。

如果是使用 JavaConfig, 可以在配置文件类加上 @EnableAspectJAutoProxy 标签,以实现自动代理。以下是示例:

1
2
3
4
5
6
7
8
9
@Configuration
@EnableAspectJAutoProxy
@ComponentScan
public class ConcertConfig {  @Bean
  public Audience audience() {    return new Audience();
  }
}

Spring 使用 AspectJ 进行自动代理,仅仅是使用 @AspectJ 的标签作为指引,而底层仍然是 Spring 自己的基于代理的 aspect。所以,尽管使用了 @AspectJ 标签,Spring 的 AOP 仍然只能作用在方法级别。如果要使用 AspectJ 的全部功能,就必须在运行时注入 AspectJ,而不使用 Spring 来创建基于代理的 aspect。

创建一个 around advice

前面讲解了 before 和 after 的用法,由于 around 的用法有些不同,也更有用,所以这里单讲。先看看下面的例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@Aspect
public class Audience {  @Pointcut("execution(** concert.Performance.perform(..))")
  public void performance() {}

  @Around("performance()")
  public void watchPerformance(ProceedingJoinPoint jp) {    try {      System.out.println("Silencing cell phones");
      System.out.println("Taking seats");
      jp.proceed();
      System.out.println("CLAP CLAP CLAP!!!");
    } catch (Throwable e) {      System.out.println("Demanding a refund");
    }
  }
}

使用 @Around 标签标注了 watchPerformance 方法,监听 performance()代表的 joinpoint。此时,watchPerformance 的参数 ProceedingJoinPoint 就是指这个 joinpoint。可以看到,在 jp.proceed()的前后各有一些操作,甚至在抛出异常时,也有一些处理。所以,这个方法同时实现 @Before、@AfterReturning 和 @AfterThrowing 等标签的功能,更加灵活。

需要注意的是,必须执行 joinpoint 的 proceed()方法,否则,会导致被监听的方法没有执行。

我计划完成 50 到 100 篇关于 Spring 的文章,这是第十一篇,欢迎订阅 tantanit.com,第一时间获取文章更新,本文链接地址:http://tantanit.com/springinaction4-du-shu-bi-ji-zhi-shi-yong-biao-qian-chuang-jian-aop/

谈谈 IT的文章均为原创或翻译(翻译会注明外文来源),转载请以链接形式标明本文地址: http://tantanit.com/springinaction4-du-shu-bi-ji-zhi-shi-yong-biao-qian-chuang-jian-aop/

from: http://tantanit.com/springinaction4-du-shu-bi-ji-zhi-shi-yong-biao-qian-chuang-jian-aop/

Spring in Action 4 读书笔记之使用标签创建 AOP相关推荐

  1. 《ASP.NET Core In Action》读书笔记系列五 ASP.NET Core 解决方案结构解析1

    <ASP.NET Core In Action>读书笔记系列五 ASP.NET Core 解决方案结构解析1 参考文章: (1)<ASP.NET Core In Action> ...

  2. JavaScript设计模式读书笔记(一)= 创建型设计模式

    全系列目录 JavaScript设计模式读书笔记(一)=> 创建型设计模式 JavaScript设计模式读书笔记(二)=> 结构型设计模式 JavaScript设计模式读书笔记(三)=&g ...

  3. Spring in Action 4th 学习笔记 之 AOP

    前提:本文中的AOP仅限于Spring AOP. 先说说为什么需要AOP 最简单的一个例子就是日志记录,如果想记录一些方法的执行情况,最笨的办法就是修改每一个需要记录的方法.但这,真的很笨... 好的 ...

  4. 《JavaEE框架整合开发入门到实战——Spring+SpringMVC+MyBatis》读书笔记

    加油生活,嗯,希望假期可以把这本书刷完,新年快乐,嘻嘻,今天是旧的一年里最后的一天,嗯,除夕一过,就25岁啦.希望新的一年里,学更多的东西,认识优秀的人,希望家人健康平安,希望自己少一些烦恼,总之先学 ...

  5. spring boot 503_Spring实战读书笔记第4章 面向切面的Spring

    本章内容: 面向切面编程的基本原理 通过POJO创建切面 使用@AspectJ注解 为AspectJ切面注入依赖 在软件开发中,散布于应用中多的功能被称为横切关注点(cross-cutting con ...

  6. 《Redis in action》读书笔记

    为什么80%的码农都做不了架构师?>>>    https://www.gitbook.io/book/abcfy2/redis-in-action-reading-notes 最近 ...

  7. 《Spring Boot实战》读书笔记

    2019独角兽企业重金招聘Python工程师标准>>> 一. 读后感 Spring Boot在技术圈火了好多年了,直到最近才去系统学习它,真是相见恨晚.当我在IDE编写几行代码就把W ...

  8. Spring Cloud Gateway 概述 《重新定义Spring Cloud实战》读书笔记

    什么是Spring Cloud Gateway Spring Cloud Gateway 是 Spring 官方基于 Spring 5.0.Spring Boot 2.0 和 Project Reac ...

  9. 《Java EE 开发的颠覆者:Spring Boot实战》读书笔记

    第一章 Spring基础 Spring发展阶段 xml配置 注解配置(应用的基本配置,如数据库配置采用xml文件,业务配置有注解) java配置 每一个被Spring管理的java对象都称之为bean ...

最新文章

  1. JAVA基础10-继承(1)
  2. Octavia 的 HTTPS 与自建、签发 CA 证书
  3. Image Cloud Gallery
  4. Android异步加载
  5. 【数据分析】Python数据分析学习路线个人总结
  6. Linux上安装集群版Redis
  7. Idea和使用git命令上传本地新项目到gitee上
  8. 正则只能输入数字java_正则表达式限制输入字符,数字,汉字等
  9. 【小技巧】程序运行结束后弹窗提醒
  10. 鸿蒙系统是否兼容,鸿蒙系统能不能兼容windows的所有应用软件?
  11. 混沌matlab仿真
  12. 微分中的dx和delta x
  13. android 北斗测试,安卓手机查看是否支持北斗导航系统的详细检测方法
  14. UIPATH 调用SAP BAPI
  15. 【CF819C】Mister B and Beacons on Field 数学
  16. ACP 云计算试题集
  17. man 命令显示简体中文帮助
  18. 华为云配置https访问
  19. 5G消息(RCS),到底是什么?
  20. 密码打马赛克已经不安全了!这款开源的去“马赛克“工具一秒还原

热门文章

  1. 【复杂网络】图模型在欺诈检测应用一点看法
  2. 【行业报告】中国金融科技2017专题研究报告——易观智库
  3. DALSA线阵CCD相机开发 之 opencv读取图片
  4. 深度拆解:直播带货的现状与未来?
  5. 信息革命的新世界正在到来,连睡觉都觉得浪费
  6. 每日一博 - Spring Boot Application as a Service
  7. 白话Elasticsearch48-深入聚合数据分析之 Percentiles Aggregation-percentiles百分比算法以及网站访问时延统计及Percentiles优化
  8. 计算机视觉——利用openCV与Socket结合进行远程摄像头实时视频传输并保存图片数据
  9. c 输出空格_Python编程:案例详解输出函数print
  10. 安卓使用Span富文本给某段Text文本加上波浪线