




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、使用 Spring 进行面向切面编程(AOP )6.1.简介面向切面编程(AOP )提供另外一种角度来思考程序结构,通过这种方式弥补了面向对象编程(OOP)的不足。除了类( classes)以外,AOP提供了切面。切面对关注点进行模块化,例如横切多个类型和对象的事务管理。(这些关注点术语通常称作横切(crosscutting) 关注点。)Spring的一个关键的组件就是AOP框架。尽管如此,Spring IoC容器并不依赖于AOP,这意味着你可以自由选择是否使用 AOP , AOP 提供强大的中间件解决方案,这使得Spring IoC容器更加完善。Spring 2.0 AOPSpring 2.
2、0引入了一种更加简单并且更强大的方式来自定义切面,用户可以选择使用基于模式(schema-based)的方式或者使用 AspectJ注解。 这两种风格都完全支持通知( Advice )类型和 AspectJ 的切入点语言,虽然实际上仍然使用 Spring AOP 进行织入( Weaving )。本章主要讨论 Spring 2.0 对基于模式和基于 AspectJ 的AOP 支持。请查阅 AOP 声明风格的选择一节获取为你的应用选择适当的声明风格的建议。Spring 2.0完全保留了对Spring 1.2的向下兼容性,下一章将讨论Spring 1.2 API所提供的底层的AOP 支持。Sprin
3、g 中所使用的 AOP :提供声明式企业服务,特别是为了替代 EJB 声明式服务。 最重要的服务是 声明性事务管理(declarative transaction management ) , 这个服务建立在 Spring 的抽象事务管理( transaction abstraction )之上。允许用户实现自定义的切面,用AOP 来完善 OOP 的使用。这样你可以把Spring AOP看作是对Spring 的一种增强, 它使得 Spring 可以不需要EJB 就能提供声明式事务管理;或者也可以使用Spring AOP框架的全部功能来实现自定义的切面。本章首先介绍了 AOP 的概念, 无论你打
4、算采用哪种风格的切面声明,这个部分都值得你一读。 本章剩下的部分将着重于 Spring 2.0 对 AOP 的支持; 下一章 提供了关于 Spring 1.2 风格的 AOP 概述,也许你已经在其他书本, 文章以及已有的应用程序中碰到过这种 AOP 风格。 如果你只打算使用通用的声明式服务或者预先打包的声明式中间件服务,例如缓冲池(pooling), 那么你不必直接使用Spring AOP,而本章的大部分内容也可以直接跳过。6.1.1. AOP概念首先让我们从定义一些重要的AOP 概念开始。这些术语不是 Spring 特有的。 不幸的是,AOP 术语并不是特别的直观;如果 Spring 使用自
5、己的术语,将会变得更加令人困惑。切面( Aspect ): 一个关注点的模块化,这个关注点可能会横切多个对象。事务管理是J2EE 应用中一个关于横切关注点的很好的例子。在 Spring AOP中,切面可以使用通用类 (基于模式的风格)或者在普通类中以Aspect注解(AspectJ风格)来实现。连接点( Joinpoint ): 在程序执行过程中某个特定的点,比如某方法调用的时候或者处理异常的时候。在 Spring AOP中,一个连接点总是代表一个方法的执行。通过声明一个 org.aspectj.lang.JoinPoint类型的参数可以使通知(Advice )的主体部分获得连接点信息。通知(
6、 Advice ): 在切面的某个特定的连接点( Joinpoint )上执行的动作。 通知有各种类型, 其中包括“ around ”“、before ” 和“ after ”等通知通。知的类型将在后面部分进行讨论。许多AOP 框架,包括Spring ,都是以拦截器做通知模型,并维护一个以连接点为中心的拦截器链。切入点( Pointcut ): 匹配连接点( Joinpoint )的断言。通知和一个切入点表达式关联,并在满足这个切入点的连接点上运行(例如,当执行某个特定名称的方法时) 。 切入点表达式如何和连接点匹配是 AOP 的核心: Spring 缺省使用 AspectJ 切入点语法。引入
7、( Introduction ): (也被称为内部类型声明(inter-typedeclaration )。声明额外的方法或者某个类型的字段。Spring 允许引入新的接口(以及一个对应的实现)到任何被代理的对象。 例如,你可以使用一个引入来使 bean 实现 IsModified 接口,以便简化缓存机制。目标对象(Target Object ): 被一个或者多个切面 ( aspect )所通知(advise )的对象。也有人把它叫做 被通知( advised )对象。 既然 Spring AOP 是通过运行时代理实现的, 这个对象永远是一个 被代理( proxied ) 对象。AOP 代理(
8、 AOP Proxy ): AOP 框架创建的对象,用来实现切面契约( aspect contract )(包括通知方法执行等功能) 。在 Spring 中, AOP 代理可以是 JDK 动态代理或者 CGLIB代理。注意: Spring 2.0最新引入的基于模式( schema-based )风格和 AspectJ 注解风格的切面声明,对于使用这些风格的用户来说,代理的创建是透明的。织入( Weaving ): 把切面( aspect )连接到其它的应用程序类型或者对象上,并创建一个被通知(advised )的对象。这些可以在编译时(例如使用AspectJ 编译器),类加载时和运行时完成。S
9、pring 和其他纯 Java AOP框架一样,在运行时完成织入。通知的类型: 前置通知 ( Before advice ): 在某连接点 ( joinpoint )之前执行的通知,但这个通知不能阻止连接点前的执行(除非它抛出一个异常)。返回后通知( After returning advice):在某连接点( join point )正常完成后执行的通知: 例如,一个方法没有抛出任何异常,正常返回。抛出异常后通知 (After throwing advice 退出时执行的通知。): 在方法抛出异常后通知( After (finally) advice ): 当某连接点退出的时候执行的通知(不
10、论是正常返回还是异常退出) 。环绕通知 (Around Advice ): 包围一个连接点 ( join point )的通知,如方法调用。这是最强大的一种通知类型。环绕通知可以在方法调用前后完成自定义的行为。它也会选择是否继续执行连接点或直接返回它们自己的返回值或抛出异常来结束执行。环绕通知是最常用的一种通知类型。 大部分基于拦截的 AOP 框架,例如 Nanning 和 JBoss4 ,都只提供环绕通知。跟 AspectJ 一样, Spring 提供所有类型的通知,我们推荐你使用尽量简单的通知类型来实现需要的功能。 例如,如果你只是需要用一个方法的返回值来更新缓存,虽然使用环绕通知也能完成
11、同样的事情,但是你最好使用After returning通知而不是环绕通知。用最合适的通知类型可以使得编程模型变得简单,并且能够避免很多潜在的错误。比如,你不需要调用 JoinPoint (用于 Around Advice)的 proceed()方法,就不会有调用的问题。在 Spring 2.0 中,所有的通知参数都是静态类型,因此你可以使用合适的类型(例如一个方法执行后的返回值类型)作为通知的参数而不是使用一个对象数组。切入点( pointcut )和连接点 ( join point )匹配的概念是 AOP 的关键,这使得 AOP 不同于其它仅仅提供拦截功能的旧技术。 切入点使得定位通知(a
12、dvice )可独立于 OO 层次。 例如,一个提供声明式事务管理的around 通知可以被应用到一组横跨多个对象中的方法上(例如服务层的所有业务操作)。 6.1.2. Spring AOP 的功能和目标Spring AOP 用纯 Java 实现。它不需要专门的编译过程。 Spring AOP 不需要控制类装载器层次, 因此它适用于 J2EEweb容器或应用服务器。Spring 目前仅支持使用方法调用作为连接点( join pointSpring bean上通知方法的执行) 。 虽然可以在不影响到)(在Spring AOP核心API的情况下加入对成员变量拦截器支持,但 Spring 并没有实现
13、成员变量拦截器。 如果你需要把对成员变量的访问和更新也作为通知的连接点,可以考虑其它语法的 Java 语言,例如 AspectJ 。Spring 实现 AOP 的方法跟其他的框架不同。 Spring 并不是要尝试提供最完整的 AOP 实现(尽管 Spring AOP 有这个能力), 相反的,它其实侧重于提供一种 AOP 实现和 SpringIoC 容器的整合, 用于帮助解决在企业级开发中的常见问题。因此, Spring AOP 通常都和 Spring IoC 容器一起使用。 Aspect 使用普通的 bean 定义语法(尽管 Spring 提供了强大的“自动代理(autoproxying )”
14、功能): 与其他 AOP 实现相比这是一个显著的区别。有些事使用Spring AOP是无法轻松或者高效的完成的,比如说通知一个细粒度的对象。这种时候,使用AspectJ是最好的选择。不过经验告诉我们:于大多数在J2EE应用中遇到的问题,只要适合AOP来解决的,Spring AOP都没有问题,Spring AOP提供了一个非常好的解决方案。Spring AOP从来没有打算通过提供一种全面的AOP 解决方案来取代 AspectJ 。 我们相信无论是基于代理( proxy-based )的框架比如说 Spring 亦或是 full-blown 的框架比如说是 AspectJ 都是很有价值的,他们之间
15、的关系应该是互补而不是竞争的关系。Spring 2.0可以无缝的整合Spring AOP ,IoC和 AspectJ ,使得所有的AOP 应用完全融入基于Spring的应用体系。这样的集成不会影响SpringAOP API 或者 AOP Alliance API兼容性。接下来的一章会详细讨论Spring 的 AOP 代理;Spring AOP保留了向下Spring AOP API 。 6.1.3.Spring 缺省使用 J2SE 动态代理( dynamic proxies )来作为 AOP 的代理。这样任何接口都可以被代理。Spring 也支持使用CGLIB 代理 . 对于需要代理类而不是代理
16、接口的时候CGLIB代理是很有必要的。如果一个业务对象并没有实现一个接口,默认就会使用CGLIB。 作为面向接口编程的最佳实践,业务对象通常都会实现一个或多个接口。但也有可能会强制使用 CGLIB , 在这种情况(希望不常有)下,你可能需要通知一个没有在接口中声明的方法,或者需要传入一个代理对象给方法作为具体类型在Spring2.0 之后, Spring 可能会提供多种其他类型的AOP 代理,包括了完整的生成类。这不会影响到编程模型。6.2.AspectJ支持AspectJ 使用了 Java 5 的注解,可以将切面声明为普通的 Java 类。 AspectJ 5发布的 AspectJ proj
17、ect 中引入了这种 AspectJ 风格。Spring 2.0 使用了和 AspectJ 5 一样的注解,使用了 AspectJ提供的一个库来做切点 ( pointcut )解析和匹配。 但是,AOP 在运行时仍旧是纯的 Spring AOP ,并不依赖于AspectJ的编译器或者织入器(weaver)。 使用 AspectJ 的编译器或者织入器(weaver )的话就可以使用完整的 AspectJ语言,我们将在Section 6.8,“Spring在 应用中使用 AspectJ ”中讨论这个问题。6.2.1.启用AspectJ支持为了在 Spring 配置中使用 AspectJ aspec
18、ts ,你必须首先启用 Spring 对基于 AspectJ aspects 的配置支持,自动代理( autoproxying )基于通知是否来自这些切面。 自动代理是指 Spring 会判断一个 bean 是否使用了一个或多个切面通知,并据此自动生成相应的代理以拦截其方法调用,并且确认通知是否如期进行。通过在你的Spring 的配置中引入下列元素来启用Spring 对AspectJ的支持:我们假使你正在使用 Appendix A, XML Schema-based configuration 所描述的 schema 支持。 关于如何在 aop 的命名空间中引入这些标签,请参见Section
19、A.2.6,“ The aopschema”如果你正在使用DTD,你仍旧可以通过在你的applicationcontext中添加如下定义来启用AspectJ支持:你需要在你的应用程序的classpath 中引入两个AspectJ 库:aspectjweaver.jar和aspectjrt.jar。 这些库可以在AspectJ的安装包( 1.5.1 或者之后的版本)中的或者也可以在Spring 依赖库的lib/aspectj6.2.2.声明一个切面lib 目录里找到,目录下找到。在启用 AspectJ 支持的情况下,在 application context 中定义的任意带有一个 Aspect
20、切面(拥有 Aspect 注解)的 bean 都将被 Spring 自动识别并用于配置在 Spring AOP 。以下例子展示了为了完成一个不是非常有用的切面所需要的最小定义:下面是在application context中的一个常见的bean定义,这个bean指向一个使用了Aspect注解的bean类:下面是NotVeryUsefulAspect类定义,使用了org.aspectj.lang.annotation.Aspect注解。packageorg.xyz;import org.aspectj.lang.annotation.Aspect;Aspectpublic class NotVe
21、ryUsefulAspect 切面(用Aspect注解的类)和其他类一样有方法和字段定义。他们也可能包括切入点,通知和引入( inter-type )声明。 6.2.3. 声明一个切入点( pointcut )回想一下,切入点决定了连接点关注的内容,使得我们可以控制通知什么时候执行。Spring AOP只支持Spring bean方法执行连接点。所以你可以把切入点看做是匹配 Spring bean 上方法的执行。 一个切入点声明有两个部分: 一个包含名字和任意参数的签名,还有一个切入点表达式,该表达式决定了我们关注那个方法的执行。在 AspectJ注解风格的AOP中,一个切入点签名通过一个普通
22、的方法定义来提供,并且切入点表达式使用Pointcut注解来表示(作为切入点签名的方法必须返回void类型)。用一个例子会帮助我们区分切入点签名和切入点表达式之间的差别,下面的例子定义了一个切入点anyOldTransfer,这个切入点将匹配任何名为 transfer 的方法的执行: Pointcut(execution(* transfer(.)/ the pointcut expressionprivate void anyOldTransfer() / the pointcut signature切入点表达式,也就是Pointcut注解的值,是正规的AspectJ 5 切入点表达式。如果
23、你想要更多了解AspectJ 的切入点语言,请参见AspectJ编程指南(如果要了解基于Java 5的扩展请参阅AspectJ 5开发手册)或者其他人写的关于AspectJ的书,例如Colyer et. al.著的EclipseAspectJ或者Ramnivas Laddad著的 AspectJ in Action。6.2.3.1.切入点指定者的支持Spring AOP支持在切入点表达式中使用如下的AspectJ 切入点指定者:其他的切入点类型完整的 AspectJ 切入点语言支持额外的切入点指定者,但是Spring 不支持这个功能。他们分别是call, initialization,prei
24、nitialization, staticinitialization, get, set, handler,adviceexecution, withincode, cflow, cflowbelow, if, this和 withincode 。 在 Spring AOP 中使用这些指定者将会导致抛出 IllegalArgumentException异常。Spring AOP支持的切入点指定者可能在将来的版本中得到扩展,不但支持更多的AspectJ切入点指定者(例如if ),还会支持某些Spring 特有的切入点指定者,比如 bean (用于匹配 bean 的名字)。 execution
25、-匹配方法执行的连接点,这是你将会用到的Spring 的最主要的切入点指定者。within -限定匹配特定类型的连接点(在使用Spring AOP的时候,在匹配的类型中定义的方法的执行)。this - 限定匹配特定的连接点 (使用 Spring AOP 的时候方法的执行),其中 bean reference ( Spring AOP 代理)是指定类型的实例。target -限定匹配特定的连接点 (使用 Spring AOP的时候方法的执行),其中目标对象(被代理的appolication object)是指定类型的实例。args -限定匹配特定的连接点(使用Spring AOP的时候方法的执行
26、),其中参数是指定类型的实例。target -限定匹配特定的连接点(使用Spring AOP的时候方法的执行) ,其中执行的对象的类已经有指定类型的注解。args -限定匹配特定的连接点(使用Spring AOP的时候方法的执行),其中实际传入参数的运行时类型有指定类型的注解。within - 限定匹配特定的连接点,其中连接点所在类型已指定注解(在使用 Spring AOP 的时候,所执行的方法所在类型已指定注解) 。annotation -限定匹配特定的连接点(使用Spring AOP的时候方法的执行) ,其中连接点的主题有某种给定的注解。因为 Spring AOP 限制了连接点必须是方法执
27、行级别的, pointcut designators 的讨论也给出了一个定义, 这个定义和AspectJ的编程指南中的定义相比显得更加狭窄。除此之外,AspectJ它本身有基于类型的语义,在执行的连接点this 和target都是指同一个对象,也就是执行方法的对象。SpringAOP 是一个基于代理的系统,并且严格区分代理对象本身(对应于 this )和背后的目标对象 (对应于 target ) 6.2.3.2. 合并切入点表达式切入点表达式可以使用using &, |和 !来合并 .还可以通过名字来指向切入点表达式。 以下的例子展示了三种切入点表达式: anyPublicOperation
28、(在一个方法执行连接点代表了任意 public 方法的执行时匹配) ; inTrading (在一个代表了在交易模块中的任意的方法执行时匹配) 和 tradingOperation (在一个代表了在交易模块中的任意的公共方法执行时匹配) 。Pointcut(execution(public * *(.)private void anyPublicOperation() Pointcut(within(com.xyz.someapp.trading.*)private void inTrading() Pointcut(anyPublicOperation() & inTrading()priv
29、ate void tradingOperation() 就上所示的,从更小的命名组件来构建更加复杂的切入点表达式是一种最佳实践。 当用名字来指定切入点时使用的是常见的 Java 成员可视性访问规则。 (比如说,你可以在同一类型中访问私有的切入点,在继承关系中访问受保护的切入点,可以在任意地方访问公共切入点。 成员可视性访问规则不影响到切入点的 匹配。 6.2.3.3. 共享常见的切入点( pointcut )定义当开发企业级应用的时候,你通常会想要从几个切面来参考模块化的应用和特定操作的集合。我们推荐定义一个“ SystemArchitecture”切面来捕捉常见的切入点表达式。一个典型的切面
30、可能看起来像下面这样:packagecom.xyz.someapp;importorg.aspectj.lang.annotation.Aspect;import org.aspectj.lang.annotation.Pointcut;Aspectpublic class SystemArchitecture /* A join point is in the web layer if the method is defined* in a type in the com.xyz.someapp.web package or any sub-package* under that.*/Poi
31、ntcut(within(com.xyz.someapp.web.*)public void inWebLayer() /* A join point is in the service layer if the method is defined* in a type in the com.xyz.someapp.service package or any sub-package* under that.*/Pointcut(within(com.xyz.someapp.service.*)public void inServiceLayer() /* A join point is in
32、 the data access layer if the method is defined* in a type in the com.xyz.someapp.dao package or any sub-package* under that.*/Pointcut(within(com.xyz.someapp.dao.*)public void inDataAccessLayer() /* A business service is the execution of any method defined on a service* interface. This definition a
33、ssumes that interfaces are placed in the* service package, and that implementation types are in sub-packages.* If you group service interfaces by functional area (for example,* in packages com.xyz.someapp.abc.service and com.xyz.def.service) then* the pointcut expression execution(* com.xyz.someapp.
34、service.*.*(.)* could be used instead.*/Pointcut(execution(*com.xyz.someapp.service.*.*(.)public void businessService() /* A data access operation is the execution of anymethod defined on a* dao interface. This definition assumes that interfaces are placed in the* dao package, and that implementatio
35、n types are in sub-packages.*/Pointcut(execution(* com.xyz.someapp.dao.*.*(.)public void dataAccessOperation() 示例中的切入点定义了一个你可以在任何需要切入点表达式的地方可引用的切面。比如,为了使 service 层事务化,你可以写成:在 Section 6.3,“ Schema-based AOP support”中讨论和标签。 在Chapter 9,事务管理中讨论事务标签。6.2.3.4.示例Spring AOP用户可能会经常使用execution pointcutdesignat
36、or 。执行表达式的格式如下:execution(modifiers-pattern? ret-type-patterndeclaring-type-pattern? name-pattern(param-pattern)throws-pattern?)除了返回类型模式(上面代码片断中的ret-type-pattern),名字模式和参数模式以外,所有的部分都是可选的。返回类型模式决定了方法的返回类型必须依次匹配一个连接点。你会使用的最频繁的返回类型模式是*,它代表了匹配任意的返回类型。一个全称限定的类型名将只会匹配返回给定类型的方法。名字模式匹配的是方法名。你可以使用* 通配符作为所有或者部分
37、命名模式。参数模式稍微有点复杂:() 匹配了一个不接受任何参数的方法,而 (.) 匹配了一个接受任意数量参数的方法(零或者更多)。 模式(*) 匹配了一个接受一个任何类型的参数的方法。模式(*,String)匹配了一个接受两个参数的方法,第一个可以是任意类型,第二个则必须是 String 类型。 请参见 AspectJ 编程指南的 Language Semantics 部分。下面给出一些常见切入点表达式的例子。任意公共方法的执行: execution(public * *(.)任何一个以“set ”开始的方法的执行:execution(* set*(.)AccountService接口的任意方法的执行:execution(*com.xyz.service
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2025-2030年移动银行产业政府战略管理与区域发展战略研究咨询报告
- 2025-2030年疫苗行业市场现状供需分析及投资评估规划分析研究报告
- 2025-2030年电动牙刷市场现状供需分析及投资评估规划分析研究报告
- 2025-2030年果酒市场前景分析及投资策略与风险管理研究报告
- 2025-2030年机场酒店行业发展分析及发展趋势与投资前景预测研究报告
- 2025-2030年新型装配建筑行业市场现状供需分析及投资评估规划分析研究报告
- 2025-2030年搅拌泵车行业市场发展分析与发展前景及投资战略研究报告
- 2025-2030年微量元素肥料行业市场现状供需分析及投资评估规划分析研究报告
- 市政工程实地调研试题及答案
- 2025-2030年建筑材料行业市场发展现状及竞争格局与投资发展研究报告
- 安徽省皖南八校2025届高三下学期第三次联考物理试卷 含解析
- 2025-2030中国老年教育行业发展前景及发展策略与投资风险研究报告
- 2024年延安通和电业有限责任公司招聘考试真题
- 2024年新人教版英语三年级上册 U6 A learn 教学课件
- 美发店入职合同保密协议
- 2025-2030年中国肿瘤医院行业市场发展现状分析及未来趋势预测研究报告
- 茶廉文化课件
- 2024年中南大学专职辅导员招聘笔试真题
- 2025甘肃省农垦集团有限责任公司招聘生产技术人员145人笔试参考题库附带答案详解
- 2025-2030中国财务公司行业深度分析及发展前景与发展战略研究报告
- 2025年人教版小学五年级下册奥林匹克数学竞赛测试题(附参考答案)
评论
0/150
提交评论