定义AOP术语

描述切面的常用术语有:

  • 通知 (advice)
  • 切点 (pointcut)
  • 连接点 (joinpoint)

下图展示了这些概念是如何关联的

Spring 对AOP的支持

Spring提供了四种类型的Aop支持

  • 基于代理的经典SpringAop
  • 纯 POJO切面
  • @AspectJ注解驱动的切面
  • 注入式AcpectJ切面(适用于Spring各版本)

前三种,都是SpringAOP实现的变体,Spring AOP构建在动态代理的基础之上.因此Spring对Aop的支持局限于方法拦截.

Spring 在运行时通知对象

通过在代理类中包裹切面,Spring在运行期把切面织入到spring管理的bean中,如图,代理类风闸u那个了目标类,并拦截被通知方法的调用,再把调用转发给真正的目标bean. 当代理拦截到方法调用时,在调用目标bean方法之前,会执行切面逻辑.

需要注意的是:知道应用需要被代理的Bean时,spring才会创建代理对象.并且,Spring只支持方法级别的连接点.

编写切点

切点用于准确定位应该在什么地方应用切面的通知.同志和切点是切面的最基本元素.因此,了解如何编写切点非常重要.

关于Spring AOP的AspectJ切点,最重要的一点就是Spring仅支持AspectJ切点指示器(pointcutdesignator)的一个子集。 让我们回顾下,Spring是基于代理的,而某些切点表达式是与基于代理的AOP无关的。表4.1列出了Spring AOP所支持的AspectJ切点指示器。

在Spring中尝试使用AspectJ其他指示器时,将会抛出IllegalArgument-Exception异常。

为了阐述Spring中的切面,我们需要一个主题来定义切面的切点.我们定义一个 Performance 接口:

package com.itguang.demo.aop;

public interface Performance {
public void perform();
}

Performance 可以代表任何类型的现场表演,如舞台剧、电影或音乐会。假设我们想编写Performance的perform()方法触发的通知。 下图 展现了一个切点表达式,这个表达式能够设置当perform()方法执行时触发通知的调用。

我们使用 execution()指示器,选择proformance的perform()方法. 方法表达式以 * 开始,表明我们不关心方法的返回值类型.然后我们指定了全限定类名和方法名.对于方法参数列表,我们使用两个点号 (..) 表明切点要选择任意的 perform() 方法,无论方法的入参是什么

现在假设我们需要配置的切点仅匹配concert包.在此场景下,可以使用within()指示器来限制匹配.

请注意我们使用了 && 操作符把 execution()和within()指示器连接在一起形成 and 关系. 类似的,我们可以使用 || 操作符标识 or 关系,而使用 ! 操作符标识 not 操作. 因为“&”在XML中有特殊含义,所以在Spring的XML配置里面描述切点时,我们可以使用and 来代替“&&”。同样,or和not可以分别用来代替“||”和“!”。

定义切面

我们已经定义了 Performance接口,它是切面中切点的目标对象,现在让我们使用AspectJ注解来定义切面.

/**
* 观看演出的切面
*
* @author itguang
* @create 2017-11-06 16:24
**/
@Aspect
public class Audience { /**
* 手机静音
*/
@Before("execution(* com.itguang.demo.aop.Performance.perform(..))")
public void silenceCellPhone(){
System.out.println("Silence Cell Phone");
} /**
* 就做
*/
@Before("execution(* com.itguang.demo.aop.Performance.perform(..))")
public void takeSeats(){
System.out.println("Taking seats");
} /**
* 鼓掌
*/
@AfterReturning("execution(* com.itguang.demo.aop.Performance.perform(..))")
public void applause(){
System.out.println("pa pa pa");
} /**
* 表演失败(异常),退款
*/
@AfterThrowing("execution(* com.itguang.demo.aop.Performance.perform(..))")
public void demandRefund(){
System.out.println("Demanding a refund");
}
}

Audience 类使用了 @AspectJ 注解进行了标注.该注解表明 Audience不仅仅是一个 POJO,还是一个切面.Audience类中的方法都适用注解定义切面的具体行为.

Audience有四个方法,定义了一个观众在观看演出时可能会做的事情。在演出之前,观众要 就坐(takeSeats())并将手机调至静音状态(silenceCellPhones())。如果演出很精彩 的话,观众应该会鼓掌喝彩(applause())。不过,如果演出没有达到观众预期的话,观众会 要求退款(demandRefund())。

AspectJ提供了5个注解来定义通知 

上面的代码 相同的切点表达式我们重复了四遍,这样的重复让人感觉有些不对劲。如果我们只定义这个切点一次,然后每次需要的时候引用它,那么这会是一个很好的方案。 幸好,我们完全可以这样做:@Pointcut注解能够在一个@AspectJ切面内定义可重用的切点.

/**
* 观看演出的切面
*
* @author itguang
* @create 2017-11-06 16:49
**/
@Aspect
public class Audience2 { @Pointcut("execution(* com.itguang.demo.aop.Performance.perform(..))")
public void performance(){ } /**
* 手机静音
*/
@Before("performance()")
public void silenceCellPhone(){
System.out.println("Silence Cell Phone");
} /**
* 就做
*/
@Before("performance()")
public void takeSeats(){
System.out.println("Taking seats");
} /**
* 鼓掌
*/
@AfterReturning("performance()")
public void applause(){
System.out.println("pa pa pa");
} /**
* 表演失败(异常),退款
*/
@AfterThrowing("performance()")
public void demandRefund(){
System.out.println("Demanding a refund");
}
}

performance()方法的实际内容并不重要,在这里它实际上应该是空的。其实该方法本身只是一个标识,供@Pointcut注解依附。

需要注意的是,除了注解和没有实际操作的performance()方法,Audience类依然是一个 POJO。我们能够像使用其他的Java类那样调用它的方法,它的方法也能够独立地进行单元测 试,这与其他的Java类并没有什么区别。Audience只是一个Java类,只不过它通过注解表明 会作为切面使用而已。

像其他的Java类一样,它可以装配为Spring中的bean:

 @Bean
public Audience2 audience2(){
return new Audience2();
}

如果你使用JavaConfig的话,可以在配置类的类级别上通过使用EnableAspectJAutoProxy注解启用自动代理功能。

/**
* AOP config
*
* @author itguang
* @create 2017-11-06 16:53
**/
@Configuration
@EnableAspectJAutoProxy
public class AOPConfig { @Bean
public Audience2 audience2(){
return new Audience2();
} }

不管你是使用JavaConfig还是XML,AspectJ自动代理都会为使用@Aspect注解的bean创建一个代理,这个代理会围绕着所有该切面的切点所匹配的bean。,Audience类中的通知方法将会在perform()调用前后执行。

创建环绕通知

环绕通知是最为强大的通知类型.他能够让你所编写的逻辑将被通知的方法完全包装起来.实际上就像在一个方法中同时编写前置通知和后置通知.

/**
* 使用环绕通知的Audience切面
*
* @author itguang
* @create 2017-11-06 17:03
**/
@Aspect
public class Audience3 { @Pointcut("execution(* com.itguang.demo.aop.Performance.perform(..))")
public void performance(){
} @Around("performance()")
public void watchPerformance(ProceedingJoinPoint jp){
try {
System.out.println("Silence Cell Phone");
System.out.println("Taking seats");
//将控制权交给被通知的方法,即调用被通知的方法
jp.proceed();
System.out.println("pa pa pa");
}catch (Throwable e){
System.out.println("Demanding a refund");
}
} }

在这里,@Around 注解表明 watchPerformance()方法将会作为 perdormance() 切点的环绕通知.

关于这个心得通知方法,你注意到的可能是 它接受ProceedingJoinPoint 作为参数.这个对象是必须要有的,因为你要在通知中通过它来调用被通知的方法.

需要注意的是,别忘记调用proceed()方法。如果不调这个方法的话,那么你的通知实际上 会阻塞对被通知方法的调用。有可能这就是你想要的效果,但更多的情况是你希望在某个点 上执行被通知的方法。

有意思的是,你可以不调用proceed()方法,从而阻塞对被通知方法的访问,与之类似,你也 可以在通知中对它进行多次调用。要这样做的一个场景就是实现重试逻辑,也就是在被通知 方法失败后,进行重复尝试。

处理通知中的参数

上图中需要关注的是切点表达式中的argus(trackNumber) 限定符. 它表示传递给 playTrack() 方法的 int类型的 参数也会传到通知中去. 参数的名称 trackNumber也与切点方法签名中的参数相匹配.

Spring AOP 面向切面的Spring的更多相关文章

  1. Spring使用笔记(四) 面向切面的Spring

    面向切面的Spring 一.面向切面的概念 在软件开发中,散布于应用多处的功能被称为横切关注点(cross-cutting concern). 通常来讲这些横切关注带点从概念上来讲是与应用逻辑相分离的 ...

  2. Spring实战第四章学习笔记————面向切面的Spring

    Spring实战第四章学习笔记----面向切面的Spring 什么是面向切面的编程 我们把影响应用多处的功能描述为横切关注点.比如安全就是一个横切关注点,应用中许多方法都会涉及安全规则.而切面可以帮我 ...

  3. 第04章-面向切面的Spring

    1. 什么是面向切面编程 AOP是什么 切面帮助我们模块化横切关注点. 横切关注点可被描述为影响应用[多处的]功能.如安全,应用许多方法会涉及安全规则. 继承与委托是最常见的实现重用 通用功能 的面向 ...

  4. 五、面向切面的spring(1)

    spring的依赖注入看完了,接下来是spring中与DI一并重要的AOP了,开始吧,GO. 在软件开发中,散布于应用中多处的功能被称为横切发关注点,通常来讲,这些横切关注点从概念上市与应用的业务逻辑 ...

  5. Spring学习(四)--面向切面的Spring

    一.Spring--面向切面 在软件开发中,散布于应用中多处的功能被称为横切关注点(cross- cutting concern).通常来讲,这些横切关注点从概念上是与应用的业 务逻辑相分离的(但是往 ...

  6. 面向切面的Spring

    在软件开发中,发布于应用中多处的功能被称为横切关注点.通常,这些横切关注点从概念上是与应用的业务逻辑相分离的(但往往直接嵌入到应用的业务逻辑之中).将横切关注点与业务逻辑相分离是AOP所要解决的. 一 ...

  7. Spring系列(四) 面向切面的Spring

    除了IOC外, AOP是Spring的另一个核心. Spring利用AOP解决应用横切关注点(cross-cutting concern)与业务逻辑的分离, 目的是解耦合. 横切关注点是指散布于代码多 ...

  8. Spring学习笔记(三):面向切面的Spring

    Spring之面向切面编程 一.理解何为面向切面编程 对于这个的理解,我觉得Spring实战中的例子讲得很明白: 假设我现在是一个小区用户,每个月小区都要收电费,这时候就会来人查看电表,算出来这个月电 ...

  9. 六、面向切面的spring(2)

    这个是承接五的,这部分主要的内容是在XML中声明切面. 一.在XML中声明切面 让我们先看一下spring中的AOP配置元素有哪些: AOP配置元素 用途 <aop:advisor> 定义 ...

随机推荐

  1. ABP开发框架前后端开发系列---(11)菜单的动态管理

    在前面随笔<ABP开发框架前后端开发系列---(9)ABP框架的权限控制管理>中介绍了基于ABP框架服务构建的Winform客户端,客户端通过Web API调用的方式进行获取数据,从而实现 ...

  2. 点菜网---Java开源生鲜电商平台-系统架构图(源码可下载)

    点菜网---Java开源生鲜电商平台-系统架构图(源码可下载) 1.点菜网-生鲜电商平台的价值与定位. 生鲜电商平台是一家致力于打造全国餐饮行业智能化.便利化.平台化与透明化服务的创新型移动互联网平台 ...

  3. SpringBoot启动访问JSP页面,直接进入页面或者访问不到,报404,并且加载tomcat插件tomcat-embed-jasper也不行

    这个问题花费了两天的时间,解决路径: 我用的是SpringBoot1.5.2,SpringMVC和Spring,tomcat启动插件都是默认的版本,Spring是4.3.7,jdk是1.7.0_80, ...

  4. 视频直播:Windows中各类画面源的截取和合成方法总结

    当今,视频直播技术和实时音视频技术已经是很多行业必备,典型的应用场景有教育直播.远程视频会议.互联网娱乐等.在移动端发起直播,其画面源的种类是十分有限的,无非是取摄像头.截屏等.PC端由于其系统资源充 ...

  5. vs2017无法启动iis express

    当遇到vs2017无法启动iis express时,可尝试删除项目下的.vs文件夹,通常可解决问题

  6. 使用release自动打包发布正式版详细教程

    昨天写了个release插件的版本管理,今天就在自动发布过程中遇到了许多坑,只能再写一篇自动发布详细教程,纪念我那昨日逝去的青春 (╥ _ ╥`) release正常打包发布流程按照如下几个阶段: C ...

  7. .NET开发框架(四)-服务器IIS安装教程

    Windows Server 2012 R2 配置篇,包括服务器IIS安装.网络负载均衡器安装.ASP.NET Core 安装. 前三篇教程中,我们分享了框架的功能与视频演示介绍(文尾扫码 加入 框架 ...

  8. SPOJ MINSUB - Largest Submatrix(二分+单调栈)

    http://www.spoj.com/problems/MINSUB/en/ 题意:给出一个n*m的矩阵M,和一个面积k,要使得M的子矩阵M'的最小元素最大并且面积大于等于k,问子矩阵M'的最小元素 ...

  9. django基础知识之URLconf:

    URLconf 在settings.py文件中通过ROOT_URLCONF指定根级url的配置 urlpatterns是一个url()实例的列表 一个url()对象包括: 正则表达式 视图函数 名称n ...

  10. TPL DataFlow .Net 数据流组件,了解一下

    回顾上文 作为单体程序,依赖的第三方服务虽不多,但是2C的程序还是有不少内容可讲: 作为一个常规互联网系统,无外乎就是接受请求.处理请求,输出响应. 由于业务渐渐增长,数据处理的过程会越来越复杂和冗长 ...