Spring4.0 学习(第二天)-------Spring AOP 核心概念

并不是所有的AOP框架都是相同的,它们在连接点模型上可能有强弱之分。有些允许在字段修饰符级别应用通知,而另一些只支持与方法调用相关的连接点。它们织入切面的方式和时机也有所不同。但是无论如何,创建切点来定义切面所织入的连接点是AOP框架的基本功能。

Spring提供了4种类型的AOP支持:

1. 基于代理的经典Spring AOP; (不解释)

2. 纯POJO切面; (需要XML配置)

3. @AspectJ注解驱动的切面; (于能够不使用XML来完成功能)

4 .注入式AspectJ切面(适用于Spring各版本,若AOP需求超过了简单的方法调用(如构造器或属性拦截),则使用)

Spring通知是Java编写的

Spring所创建的通知都是用标准的Java类编写的。这样我们就可以使用与普通Java开发一样的集成开发环境(IDE)来开发切面。而 且,定义通知所应用的切点通常会使用注解或在Spring配置文件里采用XML来编写。

Spring在运行时通知对象

通过在代理类中包裹切面,Spring在运行期把切面织入到Spring管理的bean中。如图4.3所示,代理类封装了目标类,并拦截被通知方法的调用,再把调用转发给真正的目标bean。当代理拦截到方法调用时,在调用目标bean方法之前,会执行切面逻辑。

直到应用需要被代理的bean时,Spring才创建代理对象。如果使用的是ApplicationContext的话,在ApplicationContextBeanFactory中加载所有bean的时候,Spring才会创建被代理的对象。因为Spring运行时才创建代理对象,所 以我们不需要特殊的编译器来织入Spring AOP的切面。

Spring只支持方法级别的连接点

 

通过切点来选择连接点

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

Spring AOP中,要使用AspectJ的切点表达式语言来定义切点。

AspectJ切点指示器

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

 

   当我们查看如上所展示的这些Spring支持的指示器时,注意只有execution指示器是实际执行匹配的,而其他的指示器都是用来限制匹配的。这说明execution指示器是我们在编写切点定义时最主要使用的指示器。在此基础上,我们使用其他指示器来限制所匹配的切点。在Spring中尝试使用AspectJ其他指示器时,将会抛出IllegalArgument-Exception异常。

 

  编写切点----->使用注解创建切面----->XML中声明切面

 

  编写切点

      

           切点表达式:这个表达式能够设置当perform()方法执行时触发通知的调用。

  

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

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

              

我们使用了&&操作符把execution()within()指示器连接在一起形成与(and)关系(切点必须匹配所有的指示器)。类似地,我们可以使用||操作符来标识或(or)关系,而使用!操作符来标识非(not)操作。因为&XML中有特殊含义,所以在SpringXML配置里面描述切点时,我们可以使用and来代替&&。同样,ornot可以分别用来代 ||!

在切点中选择bean

Spring还引入了一个新的bean()指示器,它允许我们在切点表达式中使用beanID来标识beanbean()使用 bean IDbean名称作为参数来限制切点只匹配特定的bean

在这里,我们希望在执行Performanceperform()方法时应用通知,但限定beanIDwoodstock

在某些场景下,限定切点为指定的bean或许很有意义,但我们还可以使用非操作为除了特定ID以外的其他bean应用通知:

在此场景下,切面的通知会被编织到所有ID不为woodstockbean中。

使用注解创建切面

          定义切面  

如果一场演出没有观众的话,那不能称之为演出。对不对?从演出的角度来看,观众是非常重要的,但是对演出本身的功能来讲,它并不是核 心,这是一个单独的关注点。因此,将观众定义为一个切面,并将其应用到演出上就是较为明智的做法。

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

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

 

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

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

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

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

如果你就此止步的话,Audience只会是Spring容器中的一个bean。即便使用了AspectJ注解,但它并不会被视为切面,这些注解不会解析,也不会创建将其转换为切面的代理。 如果你使用JavaConfig的话,可以在配置类的类级别上通过使用EnableAspectJ-AutoProxy注解启用自动代理功能。

如何在JavaConfig中启用自动代理(在配置类的类级别上通过使用EnableAspectJ-AutoProxy注解启用自动代理功能)

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

SpringAspectJ自动代理仅仅使用@AspectJ作为创建切面的指导,切面依然是基于代理的。在本质上,它依然是Spring基于代理的切面。这一点非常重要,因为这意味着尽管使用的是@AspectJ注解,但我们仍然限于代理方法的调用。如果想利用AspectJ的所有能力,我们必须在运行时使用AspectJ并且不依赖Spring来创建基于代理的切面。

创建环绕通知

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

@Around注解

 

XML中声明切面

 

 注入AspectJ切面

虽然Spring AOP能够满足许多应用的切面需求,但是与AspectJ相比,Spring AOP 是一个功能比较弱的AOP解决方案。AspectJ提供了Spring AOP所不能支持的许多类型的切点。

对于大部分功能来讲,AspectJ切面与Spring是相互独立的。虽然它们可以织入到任意的Java应用中,这也包括了Spring应用,但是在应用AspectJ切面时几乎不会涉及到Spring但是精心设计且有意义的切面很可能依赖其他类来完成它们的工作。如果在执行通知时,切面依赖于一个或多个类,我们可以在切面内部实例化这些协作的对象。但更好的方式是,我们可以借助Spring的依赖注入把bean装配进AspectJ切面中。

小结

AOP是面向对象编程的一个强大补充。通过AspectJ,我们现在可以把之前分散在应用各处的行为放入可重用的模块中。我们显示地声明在何处如何应用该行为。这有效减少了代码冗余,并让我们的类关注自身的主要功能。 Spring提供了一个AOP框架,让我们把切面插入到方法执行的周围。现在我们已经学会如何把通知织入前置、后置和环绕方法的调用中,以及 为处理异常增加自定义的行为。

关于在Spring应用中如何使用切面,我们可以有多种选择。通过使用@AspectJ注解和简化的配置命名空间,在Spring中装配通知和切点变得 非常简单。

最后,当Spring AOP不能满足需求时,我们必须转向更为强大的AspectJ。对于这些场景,我们了解了如何使用SpringAspectJ切面注入依 赖。

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值