辛苦堆砌,转载请注明出处,谢谢!

上一篇说了Spring的依赖注入,今天再看看Spring的AOP,牵扯的AOP的理论知识,大家可以搜索一些文章了解一下,这里不做过多解释,本文主要介绍使用Spring如何实现AOP。

Spring的AOP只限于对方法进行拦截,如果有其他需求,可以考虑使用AspectJ。

Spring提供的通知有以下几种:

1.前向通知,在调用目标方法前执行,使用@Before注解

2.返回通知,在调用目标方法无异常返回后执行,使用@AfterReturning注解

3.异常返回通知,在调用目标方法抛出异常后执行,使用@AfterThrowing注解

4.后向通知,在调用目标方法返回后执行,无论是正常返回还是抛出异常,使用@After注解

5.环绕通知,在调用目标方法前后都会进行通知,使用@Around注解

本篇基于上一篇的示例,给出一个新的场景,有一名计算机老师教学生如何点击鼠标选择一个图标,如何点击鼠标弹出一个上下文菜单。我们先看一下我们的Teacher类。

package com.yjp.spring.study.beans;@Component
public class Teacher {public void teachSelectAnIcon() {System.out.println("请在一个图标上点击鼠标左键");}public void selectAnIconSuccess() {System.out.println("做得好!你选中了一个图标");}public void teachShowContextMenu() {System.out.println("请点击鼠标右键");}public void showContextMenuSuccess() {System.out.println("做得好!弹出了一个上下文菜单");}}

可以看到,Teacher是一个Spring Bean(用@Component注解), 如果不使用AOP,我们需要在Computer中注入依赖,来使用teacher bean。

package com.yjp.spring.study.beans;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;@Component
public class Computer {private Mouse mouse;@Autowiredprivate Teacher teacher;@Autowiredpublic Computer(@Qualifier("blackMouse") Mouse mouse) {this.mouse = mouse;}public void selectAnIcon() {teacher.teachSelectAnIcon();mouse.clickLeft();teacher.selectAnIconSuccess();}public void contextMenu() {teacher.teachShowContextMenu();mouse.clickRight();teacher.showContextMenuSuccess();}
}

可以看到,我们需要用teacher的方法"拥抱"Computer,两者不分你我,融合得很好,但是,有一些问题,teacher和computer本就是独立的,为什么必须要求computer持有一个teacher的引用,我们就没有办法让teacher在它该出场的时候再出场吗?当然可以,这时候我们使用AOP的时候来了。我们先删除上面代码中的teacher相关的逻辑,恢复到一开始Computer的状态。

首先,启用我们的AOP,在我们的配置类上加入@EnableAspectJAutoProxy注解

@Configuration
@EnableAspectJAutoProxy
@ComponentScan({"com.yjp.spring.study.beans"})
public class ComputerConfig {
}

这样就启用了Spring的AOP,然后为Teacher类添加注解

package com.yjp.spring.study.beans;import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;@Aspect
@Component
public class Teacher {@Before("execution(* com.yjp.spring.study.beans.Computer.selectAnIcon(..))")public void teachSelectAnIcon() {System.out.println("请在一个图标上点击鼠标左键");}@After("execution(* com.yjp.spring.study.beans.Computer.selectAnIcon(..))")public void selectAnIconSuccess() {System.out.println("做得好!你选中了一个图标");}@Before("execution(* com.yjp.spring.study.beans.Computer.contextMenu(..))")public void teachShowContextMenu() {System.out.println("请点击鼠标右键");}@After("execution(* com.yjp.spring.study.beans.Computer.contextMenu(..))")public void showContextMenuSuccess() {System.out.println("做得好!弹出了一个上下文菜单");}}

首先,Teacher有@Component注解,说明它是一个Bean,之后添加了@Aspect注解,该注解说明Teacher这个Bean要作为切面使用,这里注意@Aspect注解是aspectjrt包中定义的,不是Spring的注解,需要加入依赖。然后,将几个方法使用@Before和@After进行注解,注解的参数是一个excution表达式,一般结构是

返回值类型 完整类名.方法名(参数)

其中可以用* 代表任意类型,..代表任意参数

再次运行程序,会看到如下打印

请在一个图标上点击鼠标左键
BlackMouse Left Clicked!
做得好!你选中了一个图标
请点击鼠标右键
BlackMouse Right Clicked!
做得好!弹出了一个上下文菜单

运行成功,结果还不错,但是有一点还不太好,我们是不是可以环绕通知,把对应的方法包裹起来,当然可以,在Teacher类删除之前的方法,添加新的方法和注解,如下所示:

package com.yjp.spring.study.beans;import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;@Aspect
@Component
public class Teacher {@Around("execution(* com.yjp.spring.study.beans.Computer.selectAnIcon(..))")public void selectAnIconAround(ProceedingJoinPoint jp) {try {System.out.println("环绕通知 请在一个图标上点击鼠标左键");jp.proceed();System.out.println("环绕通知 做得好!你选中了一个图标");} catch (Throwable e) {e.printStackTrace();}}@Around("execution(* com.yjp.spring.study.beans.Computer.contextMenu(..))")public void showContextMenuAround(ProceedingJoinPoint jp) {try {System.out.println("环绕通知 请点击鼠标右键");jp.proceed();System.out.println("环绕通知 弹出了一个上下文菜单");} catch (Throwable e) {e.printStackTrace();}}
}

这样就有了环绕通知,环绕通知的差别在于,使用@Around对方法进行注解,环绕通知方法有一个参数ProceedingJpinPoint,字面意思就是连接点,连接点是我们调用被环绕方法的途径,jp.proceed()之前的内容,在方法调用前执行,之后的内容,在方法调用之后执行。运行结果如下:

环绕通知 请在一个图标上点击鼠标左键
BlackMouse Left Clicked!
环绕通知 做得好!你选中了一个图标
环绕通知 请点击鼠标右键
BlackMouse Right Clicked!
环绕通知 弹出了一个上下文菜单

Spring使用AOP就是如此简单,当然,AOP还可以处理带有参数的方法,还能配合其他一些注解,限制AOP作用的条件,这些可以在使用中慢慢学习。下面给出目前的pom.xml配置供参考。

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.yjp.spring</groupId><artifactId>study</artifactId><version>0.0.1-SNAPSHOT</version><packaging>jar</packaging><name>study</name><url>http://maven.apache.org</url><properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><java.version>1.8</java.version><junit.version>4.12</junit.version><spring.version>4.3.4.RELEASE</spring.version><aspectjrt.version>1.8.9</aspectjrt.version></properties><dependencies><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>${junit.version}</version><scope>test</scope></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>${spring.version}</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-test</artifactId><version>${spring.version}</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-aspects</artifactId><version>${spring.version}</version></dependency><dependency><groupId>org.aspectj</groupId><artifactId>aspectjrt</artifactId><version>${aspectjrt.version}</version></dependency></dependencies>
</project>

Spring学习之旅(二) AOP(面向切面编程)的使用相关推荐

  1. 大数据WEB阶段Spring框架 AOP面向切面编程(二)

    Spring AOP面向切面编程(二) 一.切入点的execution表达式 execution的表达形式: execution(修饰符? 返回值类型 所在包类? 方法名(参数列表) 异常?) ?表示 ...

  2. python aop编程_学习笔记: AOP面向切面编程和C#多种实现

    AOP:面向切面编程   编程思想 OOP:一切皆对象,对象交互组成功能,功能叠加组成模块,模块叠加组成系统 类--砖头     系统--房子 类--细胞     系统--人 面向对象是非常适合做大型 ...

  3. 大数据WEB阶段Spring框架 AOP面向切面编程(一)

    Spring - AOP面向切面编程(一) 一.代理模式概述 代理的特点:(目标对象即被代理者) 实现和目标对象相同的接口 具备和目标对象的方法 代理者不仅要做目标对象的方法 , 还要做一些额外的操作 ...

  4. 【SSM】Spring系列——AOP面向切面编程

    文章目录 03 AOP面向切面编程 3.1 AOP概述 3.2 面向切面编程对有什么好处 3.3 模拟AOP框架实现 3.3.1 代码实现版本一 3.3.2 代码实现版本二 3.3.3 代码实现版本三 ...

  5. Java绝地求生—Spring AOP面向切面编程

    Java绝地求生-Spring AOP面向切面编程 背景 动态代理 构建被代理对象 自动生成代理 调用动态代理 Spring方法 方式一:使用Spring的API接口 方式二:使用自定义类 方式三:使 ...

  6. spring中AOP(面向切面编程)

    spring中AOP(面向切面编程) 面向切面编程,通过预编译方式和运行期间动态代理实现程序功能的统一维护的一种技术.AOP是OOP的延续,是软件开发中的一个热点,也是spring框架中的一个重要内容 ...

  7. Spring AOP面向切面编程

    AOP面向切面编程: AOP(Aspect Oriented Programming),即面向切面编程,它利用一种称为"横切"的技术,剖解开封装的对象内部,并将那些影响了多个类的公 ...

  8. java aop面向切面编程

    最近一直在学java的spring boot,一直没有弄明白aop面向切面编程是什么意思.看到一篇文章写得很清楚,终于弄明白了,原来跟python的装饰器一样的效果.http://www.cnblog ...

  9. Springboot 一文搞懂AOP面向切面编程

    Springboot AOP面向切面编程 AOP简介 AOP(Aspect Oriented Programming)面向切面编程,一种编程范式,指导开发者如何组织程序结构. 作用:在不惊动原始设计的 ...

最新文章

  1. [游戏引擎中文版]YU-RIS 4.5 最新中文支持版
  2. eclipse打开当前文件所在文件夹
  3. Spring Boot Debug调试
  4. apple手表android手机,Apple Watch 4发布了,安卓手机用户如何选择呢?
  5. CSS链接四种状态注意顺序、UI伪类选择器的顺序
  6. 外链引入css有哪些方式_外链怎么发才会快速收录?
  7. 【华为云技术分享】Linux内核编程环境 (2)
  8. 标准C时间与日期函数、内存函数
  9. 2021-06-04计算器简易代码
  10. 《等级保护二级基本要求》
  11. 11.7 项目:下载所有 XKCD 漫画
  12. 让oracle开机自动启动,设置CentOS下开机自动启动Oracle
  13. Copy and Paste GAN: Face Hallucination from Shaded Thumbnails
  14. 当前量子计算技术前沿是什么水平?
  15. Kafka HighLevel API与LowLevel API说明
  16. 心脏滴血漏洞(CVE-2014-0160)分析与防护
  17. 数加加众包实习生招募进行中
  18. 如何提高项目估算精准度?关键看5大影响因子
  19. Photoshop CS6软件
  20. 2022秋季信息安全技术(期末复习2)

热门文章

  1. 老师讲的真棒!javaisblank函数的使用方法
  2. MUR10060CT-ASEMI快恢复模块MUR10060CT
  3. 用千千静听练听力的小工具:Mp3字慕助手(带下载慢速Voa)
  4. 3分钟用C语言教你写个‘浪漫烟花‘---特别漂亮
  5. 顺序搜索小技巧-监视哨的作用
  6. R语言与多元线性回归+逐步回归
  7. 刷步恢复使用Unv0ver6.0.1工具已签名,附在线安装地址!
  8. 小米盒子3S刷国际版
  9. 数据挖掘复习笔记第七章——聚类
  10. java实现给MultipartFile添加水印