- Spring AOP 教程
- Spring AOP - 首页
- Spring AOP - 概述
- Spring AOP - 环境搭建
- Spring AOP - 核心概念
- Spring AOP - 通知类型
- Spring AOP - 实现
- 基于XML配置的示例
- Spring AOP - 应用
- Spring AOP - 切点方法
- Spring AOP - 前置通知
- Spring AOP - 后置通知
- Spring AOP - 返回后通知
- Spring AOP - 异常抛出后通知
- Spring AOP - 环绕通知
- 基于注解的示例
- Spring AOP - 应用
- Spring AOP - 切点方法
- Spring AOP - 前置切面
- Spring AOP - 后置通知
- Spring AOP - 返回后通知
- Spring AOP - 异常抛出后通知
- Spring AOP - 环绕通知
- Spring AOP 高级特性
- Spring AOP - 代理
- Spring AOP - 自定义注解
- Spring AOP 有用资源
- Spring AOP - 快速指南
- Spring AOP - 有用资源
- Spring AOP - 讨论
Spring AOP - 实现
Spring 支持@AspectJ 注解风格方法和基于schema的方法来实现自定义切面。
基于XML Schema
切面使用常规类以及基于XML的配置来实现。
要使用本节中描述的AOP命名空间标签,您需要导入Spring AOP schema,如下所示:
<?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>
声明切面
使用<aop:aspect>元素声明一个切面,并使用ref属性引用支持bean,如下所示。
<aop:config> <aop:aspect id = "myAspect" ref = "aBean"> ... </aop:aspect> </aop:config> <bean id = "aBean" class = "..."> ... </bean>
这里“aBean”将像您在前面章节中看到的那样,被配置和依赖注入,就像任何其他Spring bean一样。
声明切点
切点有助于确定要与不同通知一起执行的感兴趣的连接点(即方法)。在使用基于XML Schema的配置时,切点将如下定义:
<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”的切点,该切点将匹配com.tutorialspoint包下Student类中getName()方法的执行。
<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>
声明通知
您可以在<aop:aspect>内使用<aop:{通知名称}>元素声明五种通知中的任何一种,如下所示。
<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
@AspectJ 指的是将切面声明为用Java 5注解注释的常规Java类的一种风格。通过在基于XML Schema的配置文件中包含以下元素来启用@AspectJ支持。
<aop:aspectj-autoproxy/>
声明切面
切面类就像任何其他普通bean一样,可以像任何其他类一样拥有方法和字段,不同之处在于它们将用@Aspect注解,如下所示。
package org.xyz; import org.aspectj.lang.annotation.Aspect; @Aspect public class AspectModule { }
它们将像任何其他bean一样在XML中配置,如下所示。
<bean id = "myAspect" class = "org.xyz.AspectModule"> <!-- configure properties of aspect here as normal --> </bean>
声明切点
切点有助于确定要与不同通知一起执行的感兴趣的连接点(即方法)。在使用基于@AspectJ的配置时,切点声明包含两部分:
一个切点表达式,它确定我们感兴趣的哪些方法执行。
一个切点签名,包括一个名称和任意数量的参数。方法的实际主体无关紧要,实际上应该为空。
以下示例定义了一个名为“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() {}
声明通知
您可以使用@{通知名称}注解声明五种通知中的任何一种,如下所示。这假设您已经定义了一个切点签名方法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(){ ... }