Springaop 简明教程
Spring AOP - Implementations
Spring 支持 @AspectJ annotation style 方法和 schema-based 方法来实现自定义方面。
XML Schema Based
方面使用常规类和基于 XML 的配置进行实现。
若要使用本节中所述的 AOP 命名空间标签,你需要导入 Spring AOP 架构,如下所示
<?xml version = "1.0" encoding = "UTF-8"?>
<beans xmlns = "http://www.springframework.org/schema/beans"
xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop = "http://www.springframework.org/schema/aop"
xsi:schemaLocation = "http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd ">
<!-- bean definition & AOP specific configuration -->
</beans>
Declaring an Aspect
aspect 使用 <aop:aspect> 元素声明,且背景 Bean 使用 ref 特性引用,如下所示。
<aop:config>
<aop:aspect id = "myAspect" ref = "aBean">
...
</aop:aspect>
</aop:config>
<bean id = "aBean" class = "...">
...
</bean>
这里,“aBean”将被配置且依赖注入,正如你在前几章所看到的那样。
Declaring a Pointcut
Pointcut 有助于确定要使用不同的建议执行的目标连接点(即方法)。在基于 XML 架构的配置中工作时,Pointcut 将被定义如下
<aop:config>
<aop:aspect id = "myAspect" ref = "aBean">
<aop:pointcut id = "businessService"
expression = "execution(* com.xyz.myapp.service.*.*(..))"/>
...
</aop:aspect>
</aop:config>
<bean id = "aBean" class = "...">
...
</bean>
以下示例定义了一个名为“businessService”的 Pointcut,它将匹配 Student 类中可用 getName() 方法在 com.tutorialspoint 包中的执行。
<aop:config>
<aop:aspect id = "myAspect" ref = "aBean">
<aop:pointcut id = "businessService"
expression = "execution(* com.tutorialspoint.Student.getName(..))"/>
...
</aop:aspect>
</aop:config>
<bean id = "aBean" class = "...">
...
</bean>
Declaring Advices
你可以使用 <aop:{ADVICE NAME}> 元素在 <aop:aspect> 内声明任意五个建议,如下所示。
<aop:config>
<aop:aspect id = "myAspect" ref = "aBean">
<aop:pointcut id = "businessService"
expression = "execution(* com.xyz.myapp.service.*.*(..))"/>
<!-- a before advice definition -->
<aop:before pointcut-ref = "businessService"
method = "doRequiredTask"/>
<!-- an after advice definition -->
<aop:after pointcut-ref = "businessService"
method = "doRequiredTask"/>
<!-- an after-returning advice definition -->
<!--The doRequiredTask method must have parameter named retVal -->
<aop:after-returning pointcut-ref = "businessService"
returning = "retVal"
method = "doRequiredTask"/>
<!-- an after-throwing advice definition -->
<!--The doRequiredTask method must have parameter named ex -->
<aop:after-throwing pointcut-ref = "businessService"
throwing = "ex"
method = "doRequiredTask"/>
<!-- an around advice definition -->
<aop:around pointcut-ref = "businessService"
method = "doRequiredTask"/>
...
</aop:aspect>
</aop:config>
<bean id = "aBean" class = "...">
...
</bean>
你对不同的建议可以使用相同 doRequiredTask 或不同的方法。这些方法将被定义为方面模块的一部分。
@AspectJ based
@AspectJ 指一种将方面声明为使用 Java 5 注释注释的常规 Java 类的样式。通过在基于 XML 架构的配置文件中加入以下元素,可启用 @AspectJ 支持。
<aop:aspectj-autoproxy/>
Declaring an Aspect
方面类与任何其他常规 Bean 一样,可能有方法和字段,就像任何其他类一样,只不过它们将使用 @Aspect 注释,如下所示。
package org.xyz;
import org.aspectj.lang.annotation.Aspect;
@Aspect
public class AspectModule {
}
它们将在 XML 中配置,就像其他 Bean 一样,如下所示。
<bean id = "myAspect" class = "org.xyz.AspectModule">
<!-- configure properties of aspect here as normal -->
</bean>
Declaring a Pointcut
Pointcut 有助于确定要使用不同的建议执行的目标连接点(即方法)。在基于 @AspectJ 的配置中工作时,Pointcut 声明有以下两个部分
-
一个 Pointcut 表达式,用于确定我们具体对哪些方法执行感兴趣。
-
一个 Pointcut 签名,包括一个名称和任意数量的参数。方法的实际主体无关紧要,事实上应该是空的。
以下示例定义了一个名为“businessService”的切点,它将匹配包 com.xyz.myapp.service 下的类中所有可用方法的执行。
import org.aspectj.lang.annotation.Pointcut;
@Pointcut("execution(* com.xyz.myapp.service.*.*(..))") // expression
private void businessService() {} // signature
以下示例定义了一个名为“getname”的切点,它将匹配包 com.tutorialspoint 中 Student 类中 getName() 方法的执行。
import org.aspectj.lang.annotation.Pointcut;
@Pointcut("execution(* com.tutorialspoint.Student.getName(..))")
private void getname() {}
Declaring Advices
您可以使用 @{ADVICE-NAME} 注解声明以下任何五种建议。这假定您已定义了切点签名方法 businessService()。
@Before("businessService()")
public void doBeforeTask(){
...
}
@After("businessService()")
public void doAfterTask(){
...
}
@AfterReturning(Pointcut = "businessService()", returning = "retVal")
public void doAfterReturnningTask(Object retVal){
// you can intercept retVal here.
...
}
@AfterThrowing(Pointcut = "businessService()", throwing = "ex")
public void doAfterThrowingTask(Exception ex){
// you can intercept thrown exception here.
...
}
@Around("businessService()")
public void doAroundTask(){
...
}
您可以为任何建议内联定义切点。下面是为前置建议定义内联切点的示例。
@Before("execution(* com.xyz.myapp.service.*.*(..))")
public doBeforeTask(){
...
}