• 使用注解创建切面


    使用注解来创建切面是AspectJ 5所引入的关键特性。AspectJ 5之前,编写AspectJ切面需要学习一种Java语言的扩展,但是AspectJ面向注解

    的模型可以非常简便地通过少量注解把任意类转变为切面。

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

    @Pointcut注解能够在一个@AspectJ切面内定义可重用的切点

    在Audience中,performance()方法使用了@Pointcut注解。为@Pointcut注解设置的值是一个切点表达式,就像之前在通知注解上所设置的那样。通过在performance()方法上添加@Pointcut注解,我们实际上扩展了切点表达式语言,这样就可以在任何的切点表达式中使用performance()了,如果不这样做的话,你需要在这些地方使用那个更长的切点表达式。我们现在把所有通知注解中的长表达式都替换成了performance()。

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

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

    4.3展现了如何在JavaConfig中启用自动代理。。

     假如你在Spring中要使用XML来装配bean的话,那么需要使用Springaop命名空间中的<aop:aspectj-autoproxy>元素。下面的XML配置展现了如何完成该功能。

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

     

    1.2创建环绕通知

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

    关于这个新的通知方法,你首先注意到的可能是它接受ProceedingJoinPoint作为参数。这个对象是必须要有的,因为你要在通知中通过它来调用被通知的方法。通知方法中可以做任何的事情,当要将控制权交给被通知的方法时,它需要调用ProceedingJoinPoint的proceed()方法。

     需要注意的是,别忘记调用proceed()方法。如果不调这个方法的话,那么你的通知实际上会阻塞对被通知方法的调用。有可能这就是你想要的效果,但更多的情况是你希望在某个点上执行被通知的方法。有意思的是,你可以不调用proceed()方法,从而阻塞对被通知方法的访问,与之类似,你也可以在通知中对它进行多次调用。要这样做的一个场景就是实现重试逻辑,也就是在被通知方法失败后,进行重复尝试。

    1.3处理通知中的参数

    到目前为止,我们的切面都很简单,没有任何参数。唯一的例外是我们为环绕通知所编写的watchPerformance()示例方法中使用了ProceedingJoinPoint作为参数。除了环绕通知,我们编写的其他通知不需要关注传递给被通知方法的任意参数。这很正常,因为我们所通知的perform()方法本身没有任何参数。但是,如果切面所通知的方法确实有参数该怎么办呢?切面能访问和使用传递给被通知方法的参数吗?

    像之前所创建的切面一样,这个切面使用@Pointcut注解定义命名的切点,并使用@Before将一个方法声明为前置通知。但是,这里的不同点在于切点还声明了要提供给通知方法的参数。图4.6将切点表达式进行了分解,以展现参数是在什么地方指定的

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

    这个参数会传递到通知方法中,这个通知方法是通过@Before注解和命名切点trackPlayed(trackNumber)定义的。切点定义中的参数与切点方法中的参数名称是一样的,这样就完成了从命名切点到通知方法的参数转移

    1.4在XML中声明切面

    在Spring的aop命名空间中,提供了多个元素用来在XML中声明切面,如表4.3所示。

    Spring的AOP配置元素能够以非侵入性的方式声明切面

    我们已经看过了<aop:aspectj-autoproxy>元素,它能够自动代理AspectJ注解的通知类。aop命名空间的其他元素能够让我们直接在Spring配置中声明切面,而不需要使用注解。例如,我们重新看一下Audience类,这一次我们将它所有的AspectJ注解全部移除掉:

    1.5声明前置和后置通知

    你可以再把那些AspectJ注解加回来,但这并不是本节的目的。相反,我们会使用Spring aop命名空间中的一些元素,将没有注解的Audience类转换为切面。下面的程序清单4.9展示了所需要的XML。

    关于Spring AOP配置元素,第一个需要注意的事项是大多数的AOP配置元素必须在<aop:config>元素的上下文内使用。这条规则有几种例外场景,但是把bean声明为一个切面时,我们总是从<aop:config>元素开始配置的

    在<aop:config>元素内,我们可以声明一个或多个通知器、切面或者切点。在程序清单4.9中,我们使用<aop:aspect>元素声明了一个简单的切面。ref元素引用了一个POJO bean,该bean实现了切面的功能——在这里就是audience。ref元素所引用的bean提供了在切面中通知所调用的方法。

    现在切点是在一个地方定义的,并且被多个通知元素所引用。<aop:pointcut>元素定义了一个id为performance的切点。同时修改所有的通知元素,用pointcut-ref属性来引用这个命名切点。正如程序清单4.10所展示的,<aop:pointcut>元素所定义的切点可以被同一个<aop:aspect>元素之内的所有通知元素引用。如果想让定义的切点能够在多个切面使用,我们可以把<aop:pointcut>元素放在<aop:config>元素的范围内。

    1.6声明环绕通知

    在观众切面中,watchPerformance()方法包含了之前四个通知方法的所有功能。不过,所有的功能都放在了这一个方法中,因此这个方法还要负责自身的异常处理。声明环绕通知与声明其他类型的通知并没有太大区别。我们所需要做的仅仅是使用<aop:around>元素

    1.7为通知传递参数

    可以看到,我们使用了和前面相同的aop命名空间XML元素,它们会将POJO声明为切面。唯一明显的差别在于切点表达式中包含了一个参数,这个参数会传递到通知方法中。如果你将这个表达式与程序清单4.6中的表达式进行对比会发现它们几乎是相同的。唯一的差别在于这里使用and关键字而不是“&&”(因为在XML中,“&”符号会被解析为实体的开始)。我们通过练习已经使用Spring的aop命名空间声明了几个基本的切面,那么现在让我们看一下如何使用aop命名空间声明引入切面

  • 相关阅读:
    2016701010126 2016-2017-2《java程序设计》集合
    201671010126 2016-2017-2《Java程序设计》第六周
    201671010126 2016-2017-2《Java程序设计》总结
    201671010128 2017-12-17《Java程序设计》之并发
    201671010128 2017-11-10《Java程序设计》之应用程序部署(2)
    201671010128 2017-11-29《Java程序设计》之应用程序部署
    201671010128 2017-11-29《Java程序设计》之Swing用户界面组件
    201671010128 2017-11-19《Java程序设计》之事件处理技术
    201671010128 2017-11-12《Java程序设计》之图形程序设计
    201671010128 2017-11-05《Java程序设计》之集合
  • 原文地址:https://www.cnblogs.com/duan2/p/8985277.html
Copyright © 2020-2023  润新知