Spring5参考指南:基于Schema的AOP

基于Schema的AOP

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

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

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

定义Aspect

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

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

<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,以下所示:app

<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之间共享。ide

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

<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样式相同的五种建议,它们具备彻底相同的语义。spa

Before Advicepwa

在匹配的方法执行以前运行通知。它经过在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的博客

相关文章
相关标签/搜索