Spring框架学习--再谈AOP

8 篇文章 0 订阅

在Spring中声明切面的方式有两种:一是使用注解创建切面;二是在XML中声明切面。

使用注解创建切面
使用注解来创建切面是AspectJ 5所引入的关键特性。 在类上使用@AspectJ注解进行标注,表明该类不仅仅是一个POJO, 还是一个切面。Spring使用AspectJ注解来声明通知方法有下面几种。
这里写图片描述
方法上添加了@AfterThrowing注解,这表明它会在抛出异常以后执行。这些注解都给定了一个切点表达式作为它的值。要想不让相同的切点表达式重复出现多次,可以使用@Pointcut注解来解决这个问题。@Pointcut注解能够在一个@AspectJ切面内定义可重用的切点,为@Pointcut注解设置的值是一个切点表达式,通过在方法上添加@Pointcut注解,实际上是扩展了切点表达式语言, 这样就可以在任何的切点表达式中使用该方法了。

使用JavaConfig, 可以在配置类的类级别上通过使用EnableAspectJ-AutoProxy注解(@EnableAspectJAutoProxy)启用自动代理功能。 在Spring中要使用XML来装配bean, 则需要使用Spring aop命名空间中的<aop:aspectj-autoproxy>元素。

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

使用@Around创建环绕通知,而环绕通知是最为强大的通知类型。 它能够让你所编写的逻辑将被通知的目标方法完全包装起来。 实际上就像在一个通知方法中同时包含了前置通知和后置通知。
关于环绕, 它接受ProceedingJoinPoint作为参数,而这个对象是必须要有的, 因为要在通知中通过它来调用被通知的方法。 通知方法中可以做任何的事情, 当要将控制权交给被通知的方法时, 它需要调用ProceedingJoinPoint的proceed()方法。如果不调proceed()这个方法的话, 那么通知实际上会阻塞对被通知方法的调用。

使用Spring AOP, 可以为bean引入新的方法。代理拦截调用并委托给实现该方法的其他对象。当引入接口的方法被调用时, 代理会把此调用委托给实现了新接口的某个其他对象。 实际上, 一个bean的实现被拆分到了多个类中。如图所示。
这里写图片描述
可以通过@DeclareParents注解来实现为bean引入新的方法@DeclareParents注解由三部分组成:
value属性指定了哪种类型的bean要引入该接口。
defaultImpl属性指定了为引入功能提供实现的类。
@DeclareParents注解所标注的静态属性指明了要引入了接口。

当Spring发现一个bean使用了@Aspect注解时, Spring就会创建一个代理, 然后将调用委托给被代理的bean或被引入的实现, 这取决于调用的方法属于被代理的bean还是属于被引入的接口。
在Spring中, 注解和自动代理提供了一种很便利的方式来创建切面。它非常简单, 并且只涉及到最少的Spring配置。 但是, 面向注解的切面声明有一个明显的劣势: 你必须能够为通知类添加注解。 为了做到这一点, 必须要有源码。

在XML中声明切面
如果需要声明切面, 但是又不能为通知类添加注解的时候, 那么就必须使用XML配置了。在Spring的aop命名空间中, 提供了多个元素用来在XML中声明切面。Spring的AOP配置元素能够以非侵入性的方式声明切面。
这里写图片描述
关于Spring AOP配置元素, 第一个需要注意的事项是大多数的AOP配置元素必须在<aop:config>元素的上下文内使用。把bean声明为一个切面时, 总是从<aop:config>元素开始配置的。
<aop:config>元素内,可以声明一个或多个通知器、 切面或者切点。 在ref元素引用了一个POJO bean, 该bean实现了切面的功能。 ref元素所引用的bean提供了在切面中通知所调用的方法。
<aop:pointcut>元素所定义的切点可以被同一个<aop:aspect>元素之内的所有通知元素引用。 如果想让定义的切点能够在多个切面使用, 可以把<aop:pointcut>元素放在<aop:config>元素的范围内。
@DeclareParents注解为被通知的方法引入了新的方法。也可以使用Spring aop命名空间中的<aop:declare-parents>元素, 来实现相同的功能。
<aop:declare-parents>声明了此切面所通知的bean要在它的对象层次结构中拥有新的父类型。 类型匹配的接口(由types-matching属性指定) 的那些bean。在父类结构中会增加的接口(由implementinterface属性指定) 。 最后要解决的问题是新增接口中的方法实现要来自于何处(在default-impl属性中指明实现新增接口的包名和类名)。用default-impl属性用全限定类名来显式指定新增接口的实现。 还可以使用delegate-ref属性来标识,delegate-ref属性引用了一个Spring bean作为引入的委托。 这需要在Spring上下文中存在一个ID为新增接口实现类的bean。
使用default-impl来直接标识委托和间接使用delegate-ref的区别在于后者是Spring bean, 它本身可以被注入、 通知或使用其他的Spring配置。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值