1 / 20

J avaEE 程序设计 第16讲 Spring的AOP

J avaEE 程序设计 第16讲 Spring的AOP. 课程结构 教学任务 培养目标 教学时间与方式. 课程结构 :. 教学任务 :. 培养目标 : 掌握AOP的基本工作原理,学会Spirng的AOP框架,并能够应用Spring的框架进行程序开发。 教学时间与方式 : 讲授,2学时. 16.1 AOP入门 AOP是Asppect Oriented Programming的缩写,可翻译为面向方面编程。AOP并不是一个新的名词,但近年来许多技术支持AOP的实现,才造成AOP这个名词的风行。 16.1.1 AOP概述

marina
Download Presentation

J avaEE 程序设计 第16讲 Spring的AOP

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. JavaEE程序设计第16讲 Spring的AOP

  2. 课程结构 教学任务 培养目标 教学时间与方式

  3. 课程结构:

  4. 教学任务:

  5. 培养目标: 掌握AOP的基本工作原理,学会Spirng的AOP框架,并能够应用Spring的框架进行程序开发。 教学时间与方式: 讲授,2学时

  6. 16.1 AOP入门 AOP是Asppect Oriented Programming的缩写,可翻译为面向方面编程。AOP并不是一个新的名词,但近年来许多技术支持AOP的实现,才造成AOP这个名词的风行。 16.1.1 AOP概述 (1)AOP是在一个服务的流程中,插入与该服务的业务逻辑无关的系统服务逻辑,如日志,安全等。这样的逻辑称为横切关心(Cross Cutting Concern),将横切关心独立出来设计为一个对象,这样的特殊对象称为方面(Aspect)。这样的服务逻辑可应用那个到应用程序的很多地方。在AOP中,它们只需要编写一次,就可以吧它们自动在整个目标应用程序中实施。AOP着重在方面的设计及它们在目标应用程序中的织入(Weaving)。 (2)目前有两种主流的AOP实现:静态AOP和动态AOP。 静态AOP,比如AspectJ(www.apsectj.org),提供了编译器的方法来构建基于AOP的逻辑,并把它加入到应用程序中。 动态AOP,比如SpringAOP,允许在运行时把服务逻辑应用到任意一段代码中。两种不同的AOP方法都有其适用面,实际上,AOP提供了与AspectJ整合的功能。 (3)AOP与OOP(Object Oriented Programming)并不相互抵触,它们是可以相辅相成的两个设计模式。Spring AOP是实现AOP的一种技术,而且Spring AOP也是Spring中一些框架或子功能所依赖的核心。与Spring IOC一样,Spring AOP也是Spring框架的核心技术。

  7. 16.1 AOP入门 16.1.2 AOP的主要术语 AOP的许多术语都过于抽象,难以理解。但是这些术语构成了AOP的基础,下面我们对AOP的主要术语进行介绍。 (1)横切关心(Cross-cutting concern):像安全检查、事务等系统层面的服务,常被安插到一些程序中各个对象的处理流程中,这样的服务逻辑在AOP中称为横切关心。如果把横切关心直接编写在负责某业务的对象流程中,会使得维护程序的成本增高。假如某天你要从该对象中修改或移除该服务逻辑时,你需要修改所有与该服务相关的程序代码,然后重新编译;另一方面,把横切关心混杂于业务逻辑中,会使得业务对象本身的逻辑或程序的编写更为复杂。AOP通过把横切关心织入(Weave)到业务逻辑中,比较成功地解决了以上问题。 (2)方面(Aspect):将横切关心设计为独立可重用的对象,这些对象称为方面(Aspect)。 (3)连接点(Joinpoint):方面在应用程序过程时加入目标对象的业务流程中的特定点,称为连接点(Joinpoint)。连接点是AOP的核心概念之一。它用来定义你在目标程序的哪里通过AOP加入新的逻辑。 (4)通知(Advice):方面在某个具体连接点采取的行为或动作,称为通知(Advice)。实际上,通知是方面的具体实现。它是在某一特定的连接点处织入目标业务程序中的服务对象。它又分为在连接点之前执行前置通知(Before Advice)和在连接点之后执行的后置通知(Advice)。

  8. 16.1 AOP入门 16.1.2 AOP的主要术语 AOP的许多术语都过于抽象,难以理解。但是这些术语构成了AOP的基础,下面我们对AOP的主要术语进行介绍。 (5)切入点(Pointcut):切入点指定某个通知在哪些连接点被织入到应用程序之中。切入点是通知要被织入到应用程序中的所有连接点的集合。我们可以在一个文件中,例如XML文件中,定义一个通知的切入点,即它的所有连接点。 (6)织入(Weaving):将通知加入应用程序的过程,称为织入(Weaving)。对于静态AOP而言,织入是在编译时完成的,通常在编译过程中增加一个步骤。而动态AOP是在程序运行时动态织入的。 (7)目标(Target):通知被应用的对象,称为目标(Target)。 引入(Introduction):通过引入,我们可以在一个对象中加入新的方法和属性,而不用修改它的程序。具体说,可以为某个已编写、编译完成的类,在执行时期动态加入一些方法或行为,而不用修改或新增任何一个程序代码。 (8)代理(Proxy):代理是由AOP框架生成的一个对象,用来执行方面(Aspect)的内容。

  9. 16.1 AOP入门 • 16.1.3 AOP入门实例 • (1)定义一个MessageWriter类可以输出“World”,其代码如下: • Package test; • Public class MessageWriter • { • Public void writeMessage() • { • System.out.print(“World”); • } • }

  10. 16.1 AOP入门 16.1.3 AOP入门实例 (2)在不修改Message Writer的代码的前提下,要求程序在“World”的前面插入“Hello”,后面添加“!”,输出“Hello World!”。这时,我们需要应用AOP技术来解决这个问题。我们把Message Writer称作目标对象。接着,我们需要编写另一个类,名为MessageDecorator,也就是一个通知。 Package test; Import org.aopalliance.intercept.MethodInterceptor; //AOP联盟定义的标准接口,用来实现方法调用连接点的包围通知 Import org.aopalliance.intercept.MethodInvocation; //代表当前被通知的方法调用。使用该类来控制具体什么时候方法调用 Public class MessageDecorator implements MethodInterceptor { Public Object invoke(MethodInvocation invocation) throws Throwable { System.out.println(“”); System.out.println(“Hello”);//打印”Hello” System.out.println(“”); object obj=invocation.proceed();//调用目标对象的方法 System.out.println(“!”);//打印”!” Return obj; } }

  11. 16.1 AOP入门 • 16.1.3 AOP入门实例 • (3)编写一个测试类,名为AOPDemo,利用AOP的代理机制,把MessageDecorator所提供的服务逻辑织入到目标对象MessageWriter中。 • Package test; • Import org.springframework.aop.framework.ProxyFactory; • Public class AOPDemo{ • Public static void main (String args[]){ • MessageWriter target=new MessageWriter(); • ProxyFactory pf=new ProxyFactory();//创建代理对象 • Pf.addAdvice(new MessageDecorator()); • Pf.setTarget(target); • MessageWriter proxy=(MessageWriter)pf.getProxy(); • Target.writeMessage();//输出”World” • System.out.println(“”); • Proxy.writeMessage();//输出”Hello World!” • } • } • 运行AOPDemo,就会输出”Hello World!”。这样,我们就利用AOP技术,在不修改MessageWriter类的代码的前提下,成功地在”World”的前面插入“Hello”,后面添加“!”,然后输出”Hello World!”

  12. 16.2 AOP框架 Spring AOP框架是一个AOP实现框架。不同的AOP框架会有不同的AOP实现方式,主要的差别在于如何实现切入点、通知,以及它们如何被织入到应用程序中。 16.2.1 通知器(Advisor) 为了把切点和通知拉到一起,需要包含以下两者的对象:即包含应该被加入的行为(通知)及行为应该被应用的地方(切点)。 (1)Spring引入了通知器(Advisor)的概念:包含通知和切点的对象,指定应该在哪里应用通知。与通知和切点不同,通知器不是一个AOP概念,而只是一个Spring特定的术语。 (2)通知器的目的是为了让通知和切点都可以单独使用。 (3)如果使用通知而没有切点,将创建一个匹配所有方法调用的切点。在这种情况下,Spring使用标准的实例Pointcut。因此,如果想要通知所有已代理的方法,使用通知而不是通知器通常是可能的。

  13. 16.2 AOP框架 16.2.2 代理(Proxy) 如果我们要为目标对象提供通知,则必须为它们建立代理(Proxy)对象。在Spring中,为了创建代理,需要使用代理工厂(Proxy Factory)。 (1)常用的代理工厂是org.springframework.aop.framework.ProxyFactoryBean。ProxyFactoryBean是Spring提供的一个类,它是在Spring IoC环境中创建代理的最底层和最灵活的方法。它有2个最重要的属性:proxyInterfaces和interceptorName。proxyInterfaces属性是指被代理的接口;而interceptorName属性是指共同建立拦截器链的通知或通知器的名字列表。 (2)ProxyFactoryBean需要在Spring的Bean定义文件(beans-config.xml)或应用程序上下文文件(applicationContext.xml)中设定. (3)代理应用Bean的定义文件 在上面的文件中,我们声明了一个名为”helloProxy”的代理,它对应的类是org.pringframework.aop.framework.ProxyFactoryBean,并设定了它的proxyInterfaces属性和interceptorNames属性的值。 在应用程序规模比较大时,如果要提供通知的目标对象很多,则一一为它们建立代理对象是一件很麻烦的事,为此Spring提供了自动代理(Autoproxing)。这样,我们不必为每一个目标对象手工定义代理对象了。

  14. 16.2 AOP框架 16.2.3 方法拦截器(MethodInterceptor)和拦截器链(Interceptor Chain) (1)Spring的AOP框架是基于AOP联盟的API的。这是一个很小的接口集合,用于指定实现方法拦截器代码所需的签名,而这些代码可以在多个AOP框架中运行,其中最重要的是org.aopalliance.intercept.MethodInterceptor的接口。AOP联盟是在2003初,由Rod Johnson、Jon Tirsen(Nanning方面创建者及基于代理的AOP倡导者)和Bob Lee(作者及JAdvice和DynAOP AOP框架的创建者)建立的。 (2)AOP联盟的方法拦截器接口的定义如下: Public interface org.aopalliance.intercept.MethodInterceptor extends Interceptor { object invoke(MethodInvocation invocation)throws Trowable; } Invoke()方法的MethodInvocation参数暴露了被激活的方法、目标连接点、AOP代理和该方法的参数。Invoke()方法应该返回调用的结果。

  15. 16.2 AOP框架 • 16.2.3 方法拦截器(MethodInterceptor)和拦截器链(Interceptor Chain) • (3)简单的MethodInterceptor实现 • Public class DebugInterceptor implements MethodInterceptor • { • Public Object invoke(MethodInvocation invocation)throws Throwable • { • System.out.println(“Before:invocation=[“+invocation+”]”); • object rval=invocation.proceed(); • System.out.println (“invocation returned”); • return rval; • } • }. • MethodInterceptor接口上的proceed()方法被用于调用链中的下一个拦截器。如果调用proceed()的拦截器是链中最后一个,通过调用proceed()将激活目标对象上的目标方法,并且控制沿着链向后倒退。

  16. 16.3 Spring的AOP框架实例 • 16.3.1 定义业务组件 • 设计系统的核心业务组件。基于针对接口编程的原则,一个好习惯是先使用接口来定义业务组件的功能,下面使用Component来代表业务组件接口。 • Component.java代码如下: • (1)定义一个业务接口 • package springroad.demo.chap5.exampleB; • public interface Component • { •      void business1();//商业逻辑方法1 •      void business2();//商业逻辑方法2 •      void business3();//商业逻辑方法3 • } • (2)写一个Component的实现ComponentImpl类,ComponentImpl.java代码如下: • package springroad.demo.chap5.exampleB; • public class ComponentImpl implements Component { • public void business1() { •        System.out.println("执行业务处理方法1"); } •     public void business2() { •        System.out.println("执行业务处理方法2");} •     public void business3() { •        System.out.println(“执行业务处理方法3”);}}

  17. 16.3 Spring的AOP框架实例 16.3.1 定义业务组件 (3)写一个Spring的配置文件,配置业务Bean。aspect-spring.xml的内容如下: <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans"     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"     xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">     <bean id="component"        class="springroad.demo.chap5.exampleB.ComponentImpl">     </bean> </beans>

  18. 16.3 Spring的AOP框架实例 • 16.3.1 定义业务组件 • (4)然后写一个用于在客户端使用业务Bean的ComponentClient类,代码如下: • package springroad.demo.chap5.exampleB; • import org.springframework.context.ApplicationContext; • public class ComponentClient { •     public static void main(String[] args) { •     ApplicationContext context=new org.springframework.context.support.ClassPathXmlApplicationContext("springroad/demo/chap5/exampleB/aspect-spring.xml"); •     Component component=(Component)context.getBean("component"); •     component.business1(); •     System.out.println("-----------"); •     component.business2(); •     } • } • 运行程序,我们可以看到结果输出为: • 执行业务处理方法1 • ----------- • 执行业务处理方法2

  19. 16.3 Spring的AOP框架实例 16.3.2 Spring AOP的实现 这个业务Bean只是简单的执行业务方法中代码,现在由于企业级应用的需要,我们需要把业务Bean中的所有business打头所有方法中的业务逻辑前,都要作一次用户检测、启动事务操作,另外在业务逻辑执行完后需要执行结束事务、写入日志的操作。直接修改每一个方法中的代码,添加上面的逻辑,前面已经说过存在不可维护等诸多问题,是不可取的。由于安全检测、事务处理、日志记录等功能需要穿插分散在各个方法中,具有横切关注点的特性,因此我们想到使用Spring的AOP来实现。

  20. 16.3 Spring的AOP框架实例 16.3.2 Spring AOP的实现 (1)写一个用来具体处理连接点的通知Bean,这个Bean实现了MethodBeforeAdvice及AfterReturningAdvice接口。 同前面解释的一样,作为演示,我们把切面模块处理的代码直放在了AdviceBean中,实际应用中将会调用具体的处理模块来实现。 (2)接下就是在Spring配置文件中进行配置,分别配置一个代表直接业务组件的targetBean,一个用来代表通知(Advice)具体实现的adviceBean,一个代表切入点描述的pointcutBean,一个代表切面模块的aspectBean,最后是使用代理Bean来定义的业务组件。 (3)运行客户端程序,确实在调用业务组件的业务方法之前及之后都确保调用了安全检查、事务处理、日志记录等模块。细心的读取会发现,此时客户端程序中用到的component这个Bean被定义为一个ProxyFactoryBean类型,其实,也正是这个代理工厂Bean的作用,才使得客户端用到的业务组件集成了处理横切问题的功能。

More Related