面向切面的 Spring —— 如何在 XML 中声明切面?
来源:互联网 发布:macbook免费清理软件 编辑:程序博客网 时间:2024/05/09 00:35
曾经建立过这样一种原则:基于注解的配置 > 基于 Java 的配置 > 基于 XML 的配置。
Q:什么情况下使用 XML 配置声明切面?
A:如果你需要声明切面,又不能为通知类添加注解的时候,那么就必须转向 XML 配置了。
Spring 的 aop 命名空间中,提供了多个元素用来在 XML 中声明切面。
Q:如何定义切面?
A:我们将 Audience 类的所有 AspectJ 注解全部移除掉。
package concert;/** * 该类已经具备了成为 AOP 通知的所有条件。需要配置一下,就能成功预期的通知了。 */public class Audience { //表演之前:将手机调至静音状态 public void silenceCellPhones() { System.out.println("Silencing cell phones"); } //表演之前:就座 public void takeSeats() { System.out.println("Taking seats"); } //表演之后:精彩的话,观众应该会鼓掌喝彩 public void applause() { System.out.println("CLAP CLAP CLAP!!!"); } //表演失败之后:没有达到观众预期的话,观众会要求退款 public void demandRefund() { System.out.println("Demanding a refund"); }}
Q:如何声明前置和后置通知?
A:我们使用 Spring aop 命名空间,将没有注解的 Audience 类转换为切面。
<?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:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"> <!-- 启用 AspectJ 自动代理 --> <aop:aspectj-autoproxy/> <bean id="audience" class="concert.Audience"/> <!-- 大多数的 AOP 配置元素必须在<aop:config> 元素的上下文内使用 --> <!-- 在此元素内,我们可以声明一个或多个通知器、切面或者切点 --> <aop:config> <aop:aspect ref="audience"> <!-- 表演之前 --> <aop:before method="silenceCellPhones" pointcut="execution(**concert.Performance.perform(..))"/> <!-- 表演之前 --> <aop:before method="takeSeats" pointcut="execution(**concert.Performance.perform(..))"/> <!-- 表演之后 --> <aop:after-returning method="applause" pointcut="execution(**concert.Performance.perform(..))"/> <!-- 表演失败之后 --> <aop:after-throwing method="demandRefund" pointcut="execution(**concert.Performance.perform(..))"/> </aop:aspect> </aop:config></beans>
可以简化一下,使用 aop:pointcut 元素。
<?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:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"> <!-- 启用 AspectJ 自动代理 --> <aop:aspectj-autoproxy/> <bean id="audience" class="concert.Audience"/> <!-- 使用 <aop:pointcut> 定义命名切点 --> <aop:config> <aop:aspect ref="audience"> <!-- 如果想让定义的切点能够在多个切面使用,我们可以把 <aop:pointcut> 元素放在 <aop:config> 元素的范围内 --> <aop:pointcut id="performance" expression="execution(**concert.Performance.perform(..))"/> <!-- 表演之前 --> <aop:before method="silenceCellPhones" pointcut-ref="performance"/> <!-- 表演之前 --> <aop:before method="takeSeats" pointcut-ref="performance"/> <!-- 表演之后 --> <aop:after-returning method="applause" pointcut-ref="performance"/> <!-- 表演失败之后 --> <aop:after-throwing method="demandRefund" pointcut-ref="performance"/> </aop:aspect> </aop:config></beans>
Q:怎么声明环绕通知?
A:如代码所示
package concert;import org.aspectj.lang.ProceedingJoinPoint;public class Audience { public void watchPerformance(ProceedingJoinPoint joinPoint){ try { System.out.println("Silencing cell phones"); System.out.println("Taking seats"); joinPoint.proceed(); System.out.println("CLAP CLAP CLAP!!!"); } catch (Throwable throwable) { System.out.println("Demanding a refund"); } }}
<?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:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"> <!-- 启用 AspectJ 自动代理 --> <aop:aspectj-autoproxy/> <bean id="audience" class="concert.Audience"/> <aop:config> <aop:aspect ref="audience"> <aop:pointcut id="performance" expression="execution(**concert.Performance.perform(..))"/> <!-- 声明环绕通知 --> <aop:around method="watchPerformance" pointcut-ref="performance"/> </aop:aspect> </aop:config></beans>
Q:怎么为通知创建参数?
A:我们移除掉 TrackCounter 上所有的 @AspectJ 注解。
package soundsystem;import java.util.HashMap;import java.util.Map;public class TrackCounter { private Map<Integer, Integer> trackCounts = new HashMap<Integer, Integer>(); public void countTrack(int trackNumber) { int currentCount = getPlauCount(trackNumber); trackCounts.put(trackNumber, currentCount + 1); } public int getPlauCount(int trackNumber) { return trackCounts.containsKey(trackNumber) ? trackCounts.get(trackNumber) : 0; }}
借助一点 Spring XML 配置,我们能够让 TrackCounter 重新变为切面。
<?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.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"> <bean id="trackCounter" class="soundsystem.TrackCounter"/> <bean id="cd" class="soundsystem.BlankDisc"> <property name="title" value="titleValue01"/> <property name="artist" value="artistValue01"/> <property name="tracks"> <list> <value>tracksValue01</value> <value>tracksValue02</value> <value>tracksValue03</value> <value>tracksValue04</value> </list> </property> </bean> <aop:config> <aop:aspect ref="trackCounter"> <aop:pointcut id="trackPlayed" expression="execution(**soundsystem.CompactDisc.play(int)) and args(trackNumber)"/> <aop:before method="countTrack" pointcut-ref="trackPlayed"/> </aop:aspect> </aop:config></beans>
Q:怎么通过切面引入新的功能?
A:使用 Spring aop 命名空间的 aop:declare-parents 元素
<bean id="encoreableDelegate" class="concert.DefaultEncoreable"/> <aop:config> <aop:aspect> <!-- 声明了此切面所通知的 bean 要在它的对象层次结构中拥有新的父类型 本例中,类型匹配 Performance 接口(由 types-matching 属性指定)的那些 bean 在父类结构中会增加 Encoreable 接口(由 implement-interface 属性指定) 两种方式标识所引入接口的实现。本例中,我们①、使用 default-impl 属性用全限定类名来显示指定 Encoreable 的实现。 ②、或者还可以使用 delegate-ref 属性来标识 --> <!--<aop:declare-parents types-matching="concert.Performance" implement-interface="concert.Encoreable" default-impl="concert.DefaultEncoreable"/>--> <!-- delegate-ref 属性引用了一个 Spring bean 作为引入的委托 --> <aop:declare-parents types-matching="concert.Performance" implement-interface="concert.Encoreable" delegate-ref="encoreableDelegate"/> </aop:aspect> </aop:config>
使用 default-impl 来直接标识委托和间接使用 delegate-ref 的区别在于后者是 Spring bean,它本身可以被注入、通知或使用其他的 Spring 配置。
上一篇:面向切面的 Spring —— 如何使用注解创建切面?
下一篇:面向切面的 Spring —— 如何注入 AspectJ 切面?
阅读全文
0 0
- 面向切面的 Spring —— 如何在 XML 中声明切面?
- (笔记)Spring实战_面向切面的Spring(3)_在XML中声明切面
- 面向切面的 Spring —— 如何注入 AspectJ 切面?
- Spring 在XML中声明切面/AOP
- 面向切面的 Spring —— 什么是面向切面编程?
- 面向切面的 Spring —— 如何使用注解创建切面?
- <七>AOP面向切面——配置bean.xml文件方式声明切面(附源码)
- Spring面向切面编程——什么是面向切面编程
- 面向切面的Spring
- 面向切面的spring
- 面向切面的Spring
- 面向切面的Spring
- 面向切面的Spring
- Spring的面向切面编程在redis中应用
- Spring实战——面向切面的Spring
- Spring实战——面向切面的Spring
- Spring面向切面的编程
- Spring的面向切面AOP
- leetcode(287). Find the Duplicate Number
- 文件上传下载异常
- 八皇后问题
- 知乎爬虫(scrapy默认配置下单机1小时可爬取60多万条数据)
- Python之IO编程
- 面向切面的 Spring —— 如何在 XML 中声明切面?
- 如何创建一个基本JQuery的插件
- SVN
- Linux Centos7安装Oracle12c第二版本
- Html5前端图片压缩
- iOS 解决NSTimer在UITableView滑动中暂停问题
- 获取json数据和ImageLoader图片显示到listview
- HDU
- 《一个人的朝圣》读后感