zoukankan      html  css  js  c++  java
  • Spring5参考指南:基于Schema的AOP

    基于Schema的AOP

    上篇文章我们讲到了使用注解的形式来使用Spring AOP。本文我们介绍如何使用XML Schema的形式使用Spring AOP。

    要想使用本文的AOP命名空间标记,需要导入xmlns:aop=“http://www.springframework.org/schema/aop”。

    在Spring配置中,所有Aspect和Advisor元素都必须放在aop:config元素中(在应用程序上下文配置中可以有多个aop:config元素)。aop:config元素可以包含pointcut、advisor和aspect元素(请注意,这些元素必须按该顺序声明)。

    定义Aspect

    一个aspect是定义在Spring应用程序上下文的java bean对象。

    你可以使用aop:aspect元素声明一个方面,并使用ref属性引用相应的bean,如下示例所示:

        <aop:config>
            <aop:aspect id="concurrentOperationRetry" ref="concurrentOperationExecutor">
            </aop:aspect>
        </aop:config>
    
    <bean id="concurrentOperationExecutor"
              class="com.flydean.aspect.ConcurrentOperationExecutor">
            <property name="maxRetries" value="3"/>
            <property name="order" value="100"/>
        </bean>
    

    定义Pointcut

    你可以在aop:config中使用aop:pointcut来定义一个Pointcut,如下所示:

        <aop:config>
                <aop:pointcut id="idempotentOperation"
                              expression="execution(* com.flydean.service.*.*(..))
                                            and
                             @annotation(com.flydean.beans.Idempotent)"/>
    
        </aop:config>
    

    定义在顶层aop:config中的aop:pointcut可以在多个aspects和advisors之间共享。

    当组合切入点子表达式时,可以使用and、or和not关键字来代替&& || 和!,如下所示:

     <aop:pointcut id="businessService"
                expression="execution(* com.xyz.myapp.service.*.*(..)) && this(service)"/>
    
       <aop:pointcut id="businessService"
                expression="execution(* com.xyz.myapp.service.*.*(..)) and this(service)"/>
    

    定义Advice

    schema-based AOP 支持使用与@Aspectj样式相同的五种建议,它们具有完全相同的语义。

    Before Advice

    在匹配的方法执行之前运行通知。它通过在aop:aspect中声明使用的aop:before元素,如下示例所示:

        <aop:before
            pointcut-ref="dataAccessOperation"
            method="doAccessCheck"/>
    

    After Returning Advice

    After Returning Advice,在匹配的方法执行正常完成时运行。它在一个aop:aspect中声明,方式与之前的通知相同。下面的示例演示如何声明它:

    
        <aop:after-returning
            pointcut-ref="dataAccessOperation"
            method="doAccessCheck"/>
    

    正如在@Aspectj样式中一样,您可以在通知正文中获得返回值。为此,请使用returning来指定应将返回值传递到的参数的名称,如下示例所示:

       <aop:after-returning
            pointcut-ref="dataAccessOperation"
            returning="retVal"
            method="doAccessCheck"/>
    

    doAccessCheck方法必须要有声明名为retval的参数。如下所示:

    public void doAccessCheck(Object retVal) {...
    

    After Throwing Advice

    当匹配的方法引发异常退出时执行。它通过在aop:aspect中声明after-throwing 元素来实现,如下示例所示:

        <aop:after-throwing
            pointcut-ref="dataAccessOperation"
            method="doRecoveryActions"/>
    

    同样的,你可以在通知方法中获得抛出的异常,如下所示:

        <aop:after-throwing
            pointcut-ref="dataAccessOperation"
            throwing="dataAccessEx"
            method="doRecoveryActions"/>
    

    doRecoveryActions方法必须有声明名为DataAccessEx的参数,如下所示:

    public void doRecoveryActions(DataAccessException dataAccessEx) {...
    

    After (Finally) Advice

    无论匹配的方法执行如何退出,after(finally)通知都会运行。可以使用after元素声明它,如下示例所示:

       <aop:after
            pointcut-ref="dataAccessOperation"
            method="doReleaseLock"/>
    

    Around Advice

    最后一种advice是around advice的。around通知运行“around”匹配的方法执行。它有机会在方法执行之前和之后都进行工作,并确定何时、如何以及该方法真正开始执行。

    你可以使用aop:around元素来声明around advice。advice方法的第一个参数必须是ProceedingJoinPoint类型。

       <aop:around
            pointcut-ref="businessService"
            method="doBasicProfiling"/>
    

    doBasicProfiling advice的实现如下:

    public Object doBasicProfiling(ProceedingJoinPoint pjp) throws Throwable {
        // start stopwatch
        Object retVal = pjp.proceed();
        // stop stopwatch
        return retVal;
    }
    

    advice参数

    如果您希望显式地为advice方法指定参数名,可以使用advice元素的arg-names属性来指定参数名,下面是例子:

        <aop:config>
            <aop:aspect ref="profiler">
    
                <aop:pointcut id="theExecutionOfSomePersonServiceMethod"
                              expression="execution(* com.flydean.service.PersonService.getPerson(String,int))
                    and args(name, age)"/>
    
                <aop:around pointcut-ref="theExecutionOfSomePersonServiceMethod"
                            method="profile"/>
    
            </aop:aspect>
        </aop:config>
    

    相应的aspect bean定义如下:

    public class SimpleProfiler {
    
        public Object profile(ProceedingJoinPoint call, String name, int age) throws Throwable {
            StopWatch clock = new StopWatch("Profiling for '" + name + "' and '" + age + "'");
            try {
                clock.start(call.toShortString());
                return call.proceed();
            } finally {
                clock.stop();
                System.out.println(clock.prettyPrint());
            }
        }
    }
    

    profile接收两个参数。

    Advisors

    “Advisors”的概念来自于Spring中定义的AOP支持,在AspectJ中没有直接的等价物。Advisors就像一个独立的小方面,只有一条advice。

    Spring使用aop:advisor元素支持Advisor概念。您通常会看到它与事务性advice结合使用,后者在Spring中也有自己的名称空间支持。以下示例展示了advisor:

    <aop:config>
    
        <aop:pointcut id="businessService"
            expression="execution(* com.xyz.myapp.service.*.*(..))"/>
    
        <aop:advisor
            pointcut-ref="businessService"
            advice-ref="tx-advice"/>
    
    </aop:config>
    
    <tx:advice id="tx-advice">
        <tx:attributes>
            <tx:method name="*" propagation="REQUIRED"/>
        </tx:attributes>
    </tx:advice>
    

    本文的例子可以参考aop2

    更多教程请参考 flydean的博客

  • 相关阅读:
    阿里云部署SSL证书详解
    PHP网站从Apache转移到Nginx后产生404错误的原因和解决办法
    APACHE服务器出现No input file specified.的完美解决方案
    Lnmp修改php.ini配置
    CGI,FASTCGI,PHPFPM的区别
    CLR Via CSharp读书笔记(25):线程基础
    Java Network Programming FAQ.
    SchemaFree MySQL vs NoSQL
    ERROR: JDWP Unable to get JNI 1.2 environment
    Firebug Internals
  • 原文地址:https://www.cnblogs.com/flydean/p/12680382.html
Copyright © 2011-2022 走看看