1、6.3 Spring AOP面向方面编程原理:AOP概念(1)介绍完IoC之后,我们来介绍另外一个重要的概念:AOP(Aspect Oriented Programming),也就是面向方面编程的技术。AOP基于IoC基础,是对OOP的有益补充。AOP将应用系统分为两部分,核心业务逻辑(Core business concerns)及横向的通用逻辑,也就是所谓的方面Crosscutting enterprise concerns,例如,所有大中型应用都要涉及到的持久化管理(Persistent)、事务管理(Transaction Management)、安全管理(Security)、日志管理(
2、Logging)和调试管理(Debugging)等。AOP正在成为软件开发的下一个光环。使用AOP,你可以将处理aspect的代码注入主程序,通常主程序的主要目的并不在于处理这些aspect。AOP可以防止代码混乱。Spring framework是很有前途的AOP技术。作为一种非侵略性的、轻型的AOP framework,你无 使用编 的 , 可以在Java程序中使用 。这 开发 一 要对 AOP framework, 是 常一 编程。6.3.1 AOP概念我们 一些重要的AOP概念开 。方面(Aspect):一个 注 的化,这个 注 可另外横个对currency1。事务管理是J2EE应用中
3、一个很的横 注 例“。方面用Spring的Advisor 。fi (Joinpoint):程序fl 程中的 ,如方的调用 的常。通”(Advice):在 的fi ,AOPfl 的作。 种型的通” around”、before”和throws”通”。通”型将在下面。AOP Spring都是以 通”型,一个 fi 的 。入 (Pointcut): 一个通”将发的一系fi 的 。AOP 开发 入 ,例如,使用正 。入(Introduction): 方 到通”的。Spring 入 的fi 到 通”的对currency1。例如,你可以使用一个入使 对currency1IsModifiedfi ,来 化
4、。目 对currency1(Target Object): fi 的对currency1,也 作通” 代理对currency1。AOP代理(AOP Proxy):AOP 的对currency1, 通”。在Spring中,AOP代理可以是JDK代理 CGLIB代理。编(Weaving): 方面来 一个通”对currency1。这可以在编 完成(例如使用AspectJ编 ),也可以在 完成。Spring和 Java AOP一 ,在 完成入。种通”型 :Around通”: 一个fi 的通”,如方调用。这是 大的通”。Aroud通”在方调用前后完成 的 为, 们 fl fi 通 们 的 常来 fl 。
5、Before通”:在一个fi 之前fl 的通”, 这个通”不阻止fi 前的fl (除非 一个常)。Throws通”:在方常 fl 的通”。Spring提供制型的Throws通”,因此你可以书写代码捕获感兴趣的常(和 的“),不 要 Throwable Exception制型转换。After returning通”:在fi 正常完成后fl 的通”,例如,一个方正常,没有常。Around通”是 通用的通”型。大部分基于的AOP(如Nanning和Jboss 4) 提供Around通”。如同AspectJ,Spring提供所有型的通”,我们推荐你使用 为 适的通”型来 要的 为。例如,如果 是 要用
6、一个方的 来更 ,你 一个after returning通”,而不是around通”,虽然around通”也完成同 的事情。使用 适的通”型使编程型变得 单,并减少潜在错误。例如,你不 要调用在around通”中所 使用的MethodInvocation的proceed()方,因此就调用失败。入 的概念是AOP的 键, 使AOP区别于 使用的技术。入 使通”独立于OO的层次 目 。例如,提供声 事务管理的around通”可以应用到跨越个对currency1的一方上。 因此入 构成了AOP的结构要素。下面 我们一个Spring AOP的例“。在这个例“中,我们将一个before advice,这
7、 advice的代码在调用的public方开 前fl 。以下是这个before advice的代码。package com.ascenttech.springaop.test;import java.lang.reflect.Method;import org.springframework.aop.MethodBeforeAdvice;public class TestBeforeAdvice implements MethodBeforeAdvice public void before(Method m, Object args, Object target)throws Throwab
8、le System.out.println(“Hello world! (by “+ this.getClass().getName()+ “)“);fi MethodBeforeAdvice 有一个方before 要, 了advice的。before方共用3个参数, 们提供了相当丰富的信息。参数Method m是advice开 后fl 的方,方名 可以用作判断是否fl 代码的条件。Object args是传给调用的public方的参数数。当 要记日志 ,参数args和fl 方的名 都是非常有用的信息。你也可以改变传给m的参数, 要小心使用这个功;编写初主程序的程序员并不”道主程序可会和传入参
9、数的发生冲突。Object target是fl 方m对currency1的用。在下面的BeanImpl中,每个public方调用前,都会fl advice,代码如下。package com.ascenttech.springaop.test;public class BeanImpl implements Bean public void theMethod() System.out.println(this.getClass().getName()+ “.“ + new Exception().getStackTrace()0.getMethodName()+ “()“+ “ says HE
10、LLO!“);BeanImpl了下面的fi Bean,代码如下。package com.ascenttech.springaop.test;public interface Bean public void theMethod(); 虽然不是 使用fi , 面向fi 而不是面向编程是良的编程践,Spring也鼓励这 。pointcut和advice通配置文件来,因此,fi下来你 编写主方的Java代码,代码如下。package com.ascenttech.springaop.test;import org.springframework.context.ApplicationContext;
11、import org.springframework.context.support.FileSystemXmlApplicationContext;public class Main public static void main(String args) /Read the configuration fileApplicationContext ctx = new FileSystemXmlApplicationContext(“springconfig.xml“);/Instantiate an objectBean x = (Bean) ctx.getBean(“bean“);/Ex
12、ecute the public method of the bean (the test)x.theMethod();我们 读入和处理配置文件开 ,fi下来马上要 。这个配置文件将作为粘 程序不同部分的胶水。读入和处理配置文件后,我们会得到一个 工厂ctx, 一个Spring管理的对currency1都 通这个工厂来。对currency1通工厂 后 可正常使用。仅仅用配置文件 可把程序的每一部分 起来,代码如下。com.ascenttech.springaop.test.BeantheAdvisorcom.ascenttech.springaop.test.Bean.theMethod4个b
13、ean 的次序并不重要。我们在有了一个advice、一个 了正 pointcut的advisor、一个主程序和一个配置的fi ,通工厂ctx,这个fi 本身的一个用。BeanImpl和TestBeforeAdvice都是直fi配置。我们用一个惟一的ID 一个bean 素,并 了一个,这就是全部的工作。advisor通Spring framework提供的一个RegexMethodPointcutAdvisor来。我们用advisor的第一个属性来 所 的advice-bean,第二个属性 用正 了pointcut,保良的性和易读性。后配置的是bean, 可以通一个工厂来 。bean的 看起来比际上要复杂。bean是ProxyFactoryBean的一个, 是Spring framework的一部分。这个bean的 为通以下的3个属性来 。属性proxyInterface 了fi 。属性target向本地配置的一个bean,这个bean一个fi 的。属性interceptorNames是惟一 一个 的属性,这个 所有 要在beanTarget上fl 的advisor。注 ,advisor 的次序是非常重要的。