版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
Spring
基础与实践
www.目的介绍Spring两大核心技术--依赖注入(DI)和面向切面编程(AOP)。介绍Spring是如何利用这两种技术来开发松散耦合的Java应用程序。SUNWAH目录Spring介绍1依赖注入(DI)2面向切面编程(AOP)3实践4SUNWAH
1.1Spring是什么Spring是一个基于JAVA语言、开源、轻量级的DI和AOP容器框架。EJB的声明式编程模型确实简化了很多基础设施层面的开发,如事务和安全,但在部署文件维护和各种接口(home、remote/local接口)实现等方面变得很复杂。很多新技术包括AOP和DI为JavaBeans提供了很多EJB才拥有的强大功能。这些技术使用EJB那样的声明式编码模型来提供简单洁净Java对象(POJO)。负责轻量级POJO开发就是Spring框架。Spring框架是以简化J2EE应用程序开发为特定目标而创建的。使用Spring,你可以用简单的JavaBeans来实现那些以前只有EJB才能实现的功能。SUNWAH
Spring具有很多功能,可以将它们归纳为几个基本部件。Spring是一个轻量级的DI和AOP容器框架。轻量级—从大小和应用开支上说Spring都算是轻量级的。整个Spring框架可以打成一个2.5MB多一点的JAR包,并且Spring的处理开支也非常小。更重要的是,Spring是非侵入式的:基于Spring开发的应用中的对象一般不依赖于Spring的类。依赖注入—Spring提供了一种松耦合的技术,称为依赖注入(DI)。使用DI,对象是被动接受依赖类而不是自己主动去找。对象不是从容器中查找它的依赖类,而是容器在实例化对象的时候主动将它的依赖类注入给它。SUNWAH
面向切面—Spring对面向切面编程提供了强大支持,通过将业务逻辑从应用服务(如监控和事务管理)中分离出来,实现了内聚开发。应用对象只做它们该做的——业务逻辑,它们不负责(或关心)其它系统问题(如日志和事务支持)。容器—Spring是一个容器,因为它包含并且管理应用对象的生命周期和配置。你可以通过配置来设定你的Bean是单一实例,还是每次请求产生一个实例,并且设定它们之间的关联关系。Spring有别于传统的重量级EJB容器,这些容器通常很大,很笨重。框架—Spring实现了使用简单的组件配置组合成一个复杂的应用。在Spring中,应用中的对象是通过XML文件配置组合起来的。并且Spring提供了很多基础功能(事务管理、持久层集成等),这使开发人员能够专注于开发应用逻辑。SUNWAH
核心容器Spring的最底层是核心容器。Spring核心容器为Spring框架提供了基础功能。在这个模块中你会找到BeanFactory这个类,它是最基本的Spring容器和Spring的DI所依赖的基础。ApplicationContext(上下文)模块
Spring的应用上下文建立在核心容器之上。如果说核心模块中的BeanFactory使Spring成为容器的话,那么,上下文模块就是使Spring成为框架的原因。这个模块扩展BeanFactory,添加了对I18N(国际化)、应用生命周期事件以及验证的支持。SUNWAH
Spring的AOP模块
在AOP模块中,Spring对面向切面编程提供了丰富的支持。这个模块是为Spring应用开发切面的基础。与DI一样,AOP支持应用对象之间的松耦合。利用AOP,应用程序所关心的与其应用的对象关系不大。JDBC抽象及DAO模块
编写JDBC代码时总是要写一些样板式的代码,如:获得连接、创建语句、处理结果、最后关闭连接。Spring的JDBC和DAO模块把这些样板式的代码抽象出来,让你的数据库代码变得简单明了,也可以避免因为释放数据库资源失败而引起的问题。这个模块还建立了一个容易理解的数据库异常层,它建立在各种数据库错误信息之上。以后就不用再去解释那些隐晦专有的SQL错误信息了。另外,这个模块利用Spring的AOP模块为Spring应用中的对象提供事务管理服务。
SUNWAH
ORM映射集成模块JMX(Java管理扩展)JavaEE连接器API(JCA)SpringMVC框架SpringPortletMVCSpring的Web模块远程调用Java消息服务(JMS)SUNWAHHelloWorld程序代码GreetingServiceImpl负责打印问候语。packagecom.sunwah.training.spring.hello;/**
*
Greeting
ServiceImpl负责打印问候语
*/public
classGreetingServiceImplimplementsGreetingService{//问候语privateStringgreeting;publicGreetingServiceImpl(){}SUNWAH
publicGreetingServiceImpl(Stringgreeting){this.greeting=greeting;}//打印问候语public
voidsayGreeting(){System.out.println(greeting);}public
voidsetGreeting(Stringgreeting){this.greeting=greeting;}}SUNWAHXML配置文件<?xml
version="1.0"
encoding="UTF-8"?><beans
xmlns=""xmlns:xsi=""xsi:schemaLocation=""><bean
id="greetingService"
class="com.sunwah.training.spring.hello.GreetingServiceImpl"><property
name="greeting"
value="HelloWorld!"
/></bean><bean
id="greetingService2"
class="com.sunwah.training.spring.hello.GreetingServiceImpl"><constructor-arg
value="HelloWorld!"
/></bean></beans>SUNWAH
执行HelloWorld程序packagecom.sunwah.training.spring.hello;importorg.springframework.beans.factory.BeanFactory;importorg.springframework.beans.factory.xml.XmlBeanFactory;importorg.springframework.core.io.ClassPathResource;public
classHelloMain{public
static
voidmain(String[]args)throwsException{BeanFactoryfactory=newXmlBeanFactory(newClassPathResource("spring-hello.xml"));SUNWAH
//属性注入GreetingServicegreetingService=(GreetingService)factory.getBean("greetingService");greetingService.sayGreeting();//构造注入GreetingServicegreetingService2=(GreetingService)factory.getBean("greetingService");greetingService2.sayGreeting();}}SUNWAH
这段代码的用处就是载入Spring容器并且利用它得到问候服务。
这里用到的BeanFactory就是Spring容器。将spring-hello.xml文件载入容器后,main()方法调用BeanFactory的getBean()方法来得到问候服务的引用。使用这个引用,它最后调用了sayGreeting()方法。当我们运行HelloMain程序时,它在屏幕上打出“HelloWorld!”。
SUNWAH
在Spring中,组件无需自己负责与其他组件的关联。取而代之的是,容器负责把协作组件的引用给予各个组件。创建系统组件之间协作关系的这个动作是DI的关键,通常被称之为装配。SUNWAH2.1容纳你的Bean在基于Spring的应用中,应用组件在Spring范围内是激活的。容器可以创建组件,装配和配置组件,以及管理他们的整个生命周期(从new到finalize())。首先,要知道容器是组件存活的地方。容器是Spring框架的核心。Spring容器使用DI管理所有注册应用系统的组件。包括在协作组件之间建立关联。Spring提供了多种容器实现,并分为两类。Bean工厂(由org.springframework.beans.factory.BeanFactory接口定义)是最简单的容器,提供了基础的依赖注入支持。应用上下文(由org.springframework.context.ApplicationContext接口定义)建立在Bean工厂基础之上,提供了系统架构服务。SUNWAH2.1.1使用Bean工厂Bean工厂采用了工厂设计模式,这个类负责创建、分发各种类型的Bean及创建协作对象间的关联关系。Bean工厂还要参与到Bean的生命周期中,调用用户定义的初始化和销毁方法。org.springframework.beans.factory.xml.XmlBeanFactory是最常使用的BeanFactory的实现,它根据XML文件中的定义装载Bean。例:BeanFactoryfactory=newXmlBeanFactory(new("c:/beans.xml"));这段代码的意思是告诉Bean工厂从XML文件中读取Bean的定义信息。但是Bean只有在被需要的时候才被实例化。为了从BeanFactory中得到一个Bean,只要简单调用getBean()方法。
例:
MyBeanmyBean=(MyBean)factory.getBean("myBean");
当getBean()方法被调用的时候,工厂就会实例化Bean并且使用依赖注入设置Bean的属性。这样就在Spring容器中开始了Bean的生命。SUNWAH
ApplicationContext与BeanFactory另一个重要区别是关于单例的Bean是如何被载入的:
BeanFactory延迟载入所有的Bean,直到getBean()方法被调用时Bean才被创建。应用上下文会在上下文启动后预载入所有的单实例Bean。SUNWAH2.1.3Bean的生命
SUNWAH
SUNWAH
Bean在Spring应用上下文的生命周期与在Bean工厂中的生命周期只有一点不同:
如果Bean实现了ApplicationContextAware接口,setApplicationContext()方法会被调用。SUNWAH2.2创建Bean定义“表演者”接口:
packagecom.sunwah.training.spring.di;/**
*
表演者接口
*
*/public
interfacePerformer{/**
*
表演
*
@throws
PerformanceException
*/public
voidperform()throwsPerformanceException;}SUNWAH2.2.1声明一个简单的Bean定义“魔术师”类:
packagecom.sunwah.training.spring.di;/**
*魔术师类
*/public
classJugglerimplementsPerformer{ //小布袋 private
int
beanBags=3; publicJuggler(){ } publicJuggler(intbeanBags){ this.beanBags=beanBags; } public
voidperform()throwsPerformanceException{ System.out.println("JUGGLING"+beanBags+"BEANBAGS"); } public
voidsetBeanBags(intbeanBags){ this.beanBags=beanBags; }}SUNWAH
在Spring配置文件中声明Bean:<bean
id="juggler"
class="com.sunwah.training.spring.di.Juggler"
/><bean>元素是Spring中最基本的配置单元,它通知Spring创建一个对象。Id属性定义了该Bean的名称,class属性指明了它是个Juggler。当Spring容器装载该Bean时,它将采用默认的构造函数来实例化jugglerBean。实际上是采用下面的java代码来创建:newcom.sunwah.training.spring.di.Juggler();SUNWAH
使用以下代码来装载Spring应用上下文:ApplicationContextctx=newClassPathXmlApplicationContext("spring-di.xml");//默认属性值Performerjuggler=(Performer)ctx.getBean("juggler");juggler.perform();SUNWAH2.2.2通过构造函数注入注入基本类型的值:<bean
id="juggler1"
class="com.sunwah.training.spring.di.Juggler"><constructor-arg
value="6"
/></bean>
注入其他对象SUNWAH
定义“诗歌”接口:
packagecom.sunwah.training.spring.di;/**
*
*
诗歌接口
*
*/public
interfacePoem{/**
*
朗诵
*/public
voidrecite();}SUNWAH
定义“作十四行诗”类:
packagecom.sunwah.training.spring.di;/**
*十四行诗类
*/public
classSonnet29implementsPoem{private
staticString[]LINES={"When,indisgracewithfortuneandmen'seyes,","Iallalonebeweepmyoutcaststate","Andtroubledeafheavenwithmybootlesscries","Andlookuponmyselfandcursemyfate,","Wishingmeliketoonemorerichinhope,","Featuredlikehim,likehimwithfriendspossess'd,","Desiringthisman'sartandthatman'sscope,","WithwhatImostenjoycontentedleast;","Yetinthesethoughtsmyselfalmostdespising,","HaplyIthinkonthee,andthenmystate,","Liketothelarkatbreakofdayarising","Fromsullenearth,singshymnsatheaven'sgate;","Forthysweetloveremember'dsuchwealthbrings","ThatthenIscorntochangemystatewithkings."};SUNWAH
publicSonnet29(){}/**
*
朗诵
*/public
voidrecite(){for(inti=0;i<LINES.length;i++){System.out.println(LINES[i]);}}}SUNWAH
定义“会诵诗的魔术师”类:
packagecom.sunwah.training.spring.di;/**
*会诵诗的魔术师
*/public
classPoeticJugglerextendsJuggler{//诗歌privatePoempoem;publicPoeticJuggler(){super();}publicPoeticJuggler(Poempoem){super();this.poem=poem;}SUNWAH
publicPoeticJuggler(intbeanBags,Poempoem){super(beanBags);this.poem=poem;}public
voidperform()throwsPerformanceException{super.perform();System.out.println("Whilereciting...");poem.recite();}public
voidsetPoem(Poempoem){this.poem=poem;}}SUNWAH
Sonnet29在Spring配置文件中的定义:: <bean
id="sonnet29"
class="com.sunwah.training.spring.di.Sonnet29"/>PoeticJuggler在Spring配置文件中的定义:<bean
id="poeticJuggler"
class="com.sunwah.training.spring.di.PoeticJuggler"><constructor-arg
value="12"
/><constructor-arg
ref="sonnet29"
/></bean>SUNWAH2.2.3通过setter方法注入通常Bean提供一对函数用来访问属性:setXXX()和getXXX()。Spring可以通过setter注入,利用setter方法来配置属性值。Spring用setter方法把<property>元素里面设置的值注入到对象中。属性name对应对象的属性名称,属性value就是要注入的值。注入简单的数值<bean
id="juggler2"
class="com.sunwah.training.spring.di.Juggler"><property
name="beanBags"
value="9"
/></bean>SUNWAH
注入其他的Bean<bean
id="poeticJuggler1"
class="com.sunwah.training.spring.di.PoeticJuggler"><property
name="beanBags"
value="15"
/><property
name="poem"
ref="sonnet29"
/></bean>SUNWAH2.2.4选择构造函数注入还是Set注入?使用构造函数注入的优点:
构造函数注入强制使用强依赖契约。如果没有提供所有需要的依赖,一个Bean就无法被实例化。由于Bean的依赖都通过它的构造函数设置,所以没有必要再写多月的Set方法。这有助于减少代码。因为只能通过构造函数设置类的属性,这样做能有效地保证了属性的不可变性。使用构造函数注入的缺点:如果Bean有很多依赖,那么构造函数的参数列表会很长。如果一个对象已经有很多种构造方式,那么很难再提出不同的构造函数,因为构造函数只能通过参数的个数和类型来区分。•如果构造函数的参数中有两个以上是相同类型的,那么很难确定每个参数的用途。• 构造函数注入不利于自身的继承。Bean的构造函数为了给父类的私有变量赋值,需要把参数传递给super()方法。SUNWAH2.3装配集合Spring提供了4个类型的集合配置元素:集合元素用途<list>装配一列值,允许重复<set>装配值集,不允许重复<map>装配名称-值对的集合,名称和值可以是任意类型<props>装配名称-值对的集合,名称和值都必须是String类型SUNWAH
<list>和<set>对应的属性类型是array或者是java.util.Collection。<map>和<props>对应是java.util.Map和java.util.Properties。SUNWAH
使用<list>配置元素:<bean
id="hank"
class="com.springinaction.springidol.OneManBand"><property
name="instruments"><list><ref
bean="guitar"
/><ref
bean="cymbal"
/><ref
bean="harmonica"
/></list></property></bean>SUNWAH
使用<set>配置元素:<bean
id="hank"
class="com.springinaction.springidol.OneManBand"><property
name="instruments"><set><ref
bean="guitar"
/><ref
bean="cymbal"
/><ref
bean="harmonica"
/></set></property></bean>SUNWAH
使用<map>配置元素:<bean
id="hank"
class="com.springinaction.springidol.OneManBand"><property
name="instruments"><map><entry
key="GUITAR"
value-ref="guitar"
/><entry
key="CYMBAL"
value-ref="cymbal"
/><entry
key="HARMONICA"
value-ref="harmonica"
/></map></property></bean>SUNWAH
使用<props>配置元素:<bean
id="hank"
class="com.springinaction.springidol.OneManBand"><property
name="instruments"><props><prop
key="GUITAR">STRUMSTRUMSTRUM</prop><prop
key="CYMBAL">CRASHCRASHCRASH</prop><prop
key="HARMONICA">HUMHUMHUM</prop></props></property></bean>SUNWAH2.4自动装配默认情况下,Bean不会自动装配。有两个办法可以让Spring自动装配:设置需要自动装配的<bean>中的autowire属性。通过在Spring配置文件的根元素<beans>设置default-autowire属性。Spring提供了四种自动装配类型:byName—试图在容器中寻找和需要自动装配的属性名相同的Bean(或ID)。如果没有找到相符的Bean,这个属性就没有被装配上。byType—试图在容器中寻找一个与需要自动配置的属性类型相同的Bean。如果没有找到相符的Bean,这个属性就没有被装配上。如果找到超过一个相符的Bean,就会抛出异常。constructor—试图在容器中查找与需要自动装配的Bean的构造函数参数一致的一个或多个Bean。如果存在不确定Bean或构造函数,容器会抛出异常。autodetect—首先尝试使用constructor来自动装配,然后使用byType方式。SUNWAH
可以混合使用自动和手动装配。使用自动装配虽然有利于减少编写装配文件,但是自动隐藏了很多细节,缺乏透明,因此一般建议采用手动装配。SUNWAH2.5控制Bean创建默认情况下,所有SpringBean都是单一的。为了使得每次都能产生一个新的Bean实例,可以声明Bean的scope属性为prototype。SUNWAH2.5.1Bean范围化
Bean的范围化选项主要有两种:
singleton—单例,定义Bean的范围为每个Spring容器一个实例(默认值)。prototype—原型,允许Bean可以被多次实例化(每次都创建一个新实例)。例如:<bean
id="saxophone"
class="com.springinaction.springidol.Saxophone"scope="prototype"
/>SUNWAH2.5.2利用工厂方法来创建Bean在Spring应用上下文中配置的Bean都可以通过调用类的构造函数来创建,也可以通过静态工厂方法来创建。
<bean>元素有一个factory-method属性,允许指定要调用的静态方法,而不是使用构造函数内创建类的实例。
<bean
id="theStage"
class="com.springinaction.springidol.Stage"factory-method="getInstance"
/>SUNWAH2.5.3初始化和销毁Bean<bean>元素中的init-method属性指定了在Bean初始化是要调用的方法,destroy-method指定了将Bean从容器中删除时要调用的方法。<bean
id="kenny"
class="com.springinaction.springidol.Instrumentalist"init-method="tuneInstrument"
destroy-method="cleanInstrument"><property
name="song"
value="JingleBells"/><property
name="instrument"
ref="saxophone"/></bean>SUNWAH默认的初始化和销毁方法<beans>元素中的default-init-method属性设置了一个上下文定义文件中所有Bean的初始化方法,default-destroy-method设置了上下文定义文件中所有Bean的销毁方法。<?xml
version="1.0"
encoding="UTF-8"?><beans
xmlns=""xmlns:xsi=""xsi:schemaLocation=""default-init-method="tuneInstrument"
default-destroy-method="cleanInstrument">…</beans>SUNWAH2.6声明父Bean和子Bean创建一个类来扩展另一个类是面向对象的基础之一。在Java的类结构里,为了把通用的功能和属性集中起来,可以把它们定义在父类里,让子类来继承。出于同样的目的,我们从<bean>定义里扩展和继承新的<bean>。这样做还会有效地减少Spring上下文定义文件里冗余的XML。SUNWAH
为了实现Bean的继承,<bean>元素提供了两个特殊属性:parent:指明Bean的id。它对于<bean>的作用相当于关键字extends对于Java类的作用。abstract:如果设置为true,就表示<bean>声明是抽象的,不能被Spring实例化。SUNWAH2.6.1抽象基Bean类型定义两个相同类型的Bean<bean
id="kenny"
class="com.springinaction.springidol.Instrumentalist"><property
name="song"
value="JingleBells"
/><property
name="instrument"
ref="saxophone"
/></bean><bean
id="david"
class="com.springinaction.springidol.Instrumentalist"><property
name="song"
value="JingleBells"
/><property
name="instrument"
ref="saxophone"
/></bean>SUNWAH
上面两个Bean的定义可以采用继承来实现:<bean
id="baseSaxophonist"
class="com.springinaction.springidol.Instrumentalist"abstract="true"><property
name="instrument"
ref="saxophone"
/><property
name="song"
value="JingleBells"
/></bean><bean
id="kenny"
parent="baseSaxophonist"
/><bean
id="david"
parent="baseSaxophonist"
/>SUNWAH
在父Bean定义中,abstract属性设置为true,这就告诉Spring不要实例化这个Bean。父Bean不必一定是抽象的,从一个具体Bean也可以创建子Bean。在子Bean定义中,parent属性表明kenny和david都继承自baseSaxophonist。在子Bean定义中没有class属性,这是因为kenny和david不仅会继承父Bean的属性,也会继承它的类型。子Bean可以覆盖继承的属性。SUNWAH2.6.2抽象共同属性以下两个Bean有相同的属性song,而且注入的属性值也一样。<bean
id="taylor"
class="com.springinaction.springidol.Vocalist"><property
name="song"
value="SomewhereOvertheRainbow"
/></bean><bean
id="stevie"
class="com.springinaction.springidol.Instrumentalist"><property
name="instrument"
ref="guitar"
/><property
name="song"
value="SomewhereOvertheRainbow"
/></bean>SUNWAH
抽象公共属性:<bean
id="basePerformer"
abstract="true"><property
name="song"
value="SomewhereOvertheRainbow"
/></bean><bean
id="taylor"
class="com.springinaction.springidol.Vocalist"parent="basePerformer"
/><bean
id="stevie"
class="com.springinaction.springidol.Instrumentalist"parent="basePerformer"><property
name="instrument"
ref="guitar"
/></bean>SUNWAH
注意父beanbasePerformer没有class属性。这没有问题,因为子Bean会利用自己的class属性来确定自己的类型。SUNWAH2.7小结Spring框架的核心是Spring容器。Spring提供了多种实现容器的方法,这些方法可以归纳为两类:BeanFactory是最简单的容器,它提供了基本的DI和Bean装配服务。如果需要用到更高级的框架服务,就需要使用Spring的ApplicationContext。在本课中,我们介绍了如何将Bean与Spring容器装配在一起。通常,在Spring容器中使用XML来执行装配。这个XML文件包括了帮助容器执行DI的信息,以便Bean能够与其所依赖的其他Bean相关联。SUNWAH3、面向切面编程(AOP)面向切面编程(AOP)SUNWAH
在软件开发中,散布于程序中多个地点的函数被称为“交叉事务”。从概念上来说,它们一般是与程序业务逻辑分开的(但经常是直接嵌入其中的)。把这些交叉事务与业务逻辑分离开正是面向切面编程(AOP)的作用所在。SUNWAH3.1
AOP简介SUNWAH3.1.1定义AOP术语通知(Advice)切面的功能被称为“通知”。通知定义了切面是什么以及何时使用。连接点(Joinpoint) 连接点是在程序执行过程中能够插入切面的一个点。这个点可以是方法被调用时、异常被抛出时、甚至字段被编辑时。切面代码可以通过这些点插入到程序的一般流程之中,从而添加新的行为。SUNWAH
切入点(Pointcut) 一个切面不是一定要通知程序里全部的连接点。切入点可以缩小切面通知的连接点的范围。如果说通知定义了切面的“什么”和“何时”,那么切入点就定义了“何地”。切入点的定义匹配通知要接入点一个或多个连接点。切面(Aspect) 切面是通知和切入点的结合。通知和切入点共同定义了关于切面的全部内容—它的功能、在何时和何地完成其功能。SUNWAH
引入(Introduction) “引入”允许我们向现有的类添加新方法和属性。目标(Target) “目标”是被通知的对象。代理(Proxy) “代理”是向目标对象应用通知之后被创建的对象。织入(Weaving) “织入”是把切面应用到目标对象来创建新的代理对象的过程。切面在指定连接点织入到目标对象。SUNWAH
织入的时机:• 编译时:切面在目标类编译时被织入。• 类加载时:切面在目标类加载到JVM时被织入。• 运行时:切面在程序运行时的某个时刻被织入。
SUNWAH3.1.2Spring对AOP的支持创建切点来定义切面织入的连接点是AOP框架的基本功能。Spring对AOP的支持具有以下4种情况: •经典的基于代理的AOP•@AspectJ注解驱动的切面•纯POJO切面•注入式AspectJ切面 前三种都是基于代理的AOP的变体,因此,Spring对于AOP的支持局限于方法注入。SUNWAH
Spring的AOP框架的几个关键点:Spring通知是用JAVA编写的。 Spring创建的全部通知都是用标准JAVA类编写的。定义通知所应用的切点通常是以XML方式写在Spring配置文件里。Spring在运行时通知对象。 Spring利用代理类包裹切面,从而把它们织入到Spring管理的Bean里。代理类装作目标Bean,截取被通知的方法调用,再把这些调用转发到真正的目标Bean。在代理截取方法调用之后,实际调用目标Bean的方法之前,代理会执行切面逻辑。Spring只支持方法连接点。由于Spring是基于动态代理的,它只支持方法连接点。SUNWAH3.2创建经典的Spring切面定义一个观众类:packagecom.sunwah.training.spring.aop;importorg.aspectj.lang.ProceedingJoinPoint;/**
*
观众
*
*/public
classAudience{publicAudience(){}public
voidwatchPerformance(ProceedingJoinPointjp){System.out.println("Theaudienceistakingtheirseats.");System.out.println("Theaudienceisturningofftheircellphones");try{ceed();System.out.println("CLAPCLAPCLAPCLAPCLAP");}catch(Throwablethrowable){System.out.println("Boo!Wewantourmoneyback!");}}SUNWAH
//落座public
voidtakeSeats(){System.out.println("Theaudienceistakingtheirseats.");}//关闭自己的手机public
voidturnOffCellPhones(){System.out.println("Theaudienceisturningofftheircellphones");}//鼓掌public
voidapplaud(){System.out.println("CLAPCLAPCLAPCLAPCLAP");}//退票public
voiddemandRefund(){System.out.println("Boo!Wewantourmoneyback!");}}SUNWAH
使用如下XML可以把它装配为Spring的<bean>:<!--观众--><bean
id="audience"
class="com.sunwah.training.spring.aop.Audience"
/>SUNWAH3.2.1创建通知Spring的AOP里有5种类型的通知,分别由一个接口进行定义:通知类型接口Before(前)org.springframework.aop.MethodBeforeAdviceAfter-returning(返回后)org.springframework.aop.AfterReturningAdviceAfter-throwing(抛出后)org.springframework.aop.ThrowsAdviceAround(周围)ercept.MethodInterceptorIntroduction(引入)org.springframework.aop.IntroductionInterceptorSUNWAH前通知、返回后通知和抛出后通知定义观众功能如何被使用的通知:packagecom.sunwah.training.spring.aop;importjava.lang.reflect.Method;importorg.springframework.aop.AfterReturningAdvice;importorg.springframework.aop.MethodBeforeAdvice;importorg.springframework.aop.ThrowsAdvice;/**
*
*
定义观众功能如何被使用的通知(实现了三种类型的通知)
*
*/public
classAudienceAdviceimplementsMethodBeforeAdvice,AfterReturningAdvice,ThrowsAdvice{publicAudienceAdvice(){}SUNWAH
//在方法之前调用public
voidbefore(Methodmethod,Object[]args,Objecttarget)throwsThrowable{audience.takeSeats();audience.turnOffCellPhones();}//在成功返回之后调用public
voidafterReturning(Objectrtn,Methodmethod,Object[]args,Objecttarget)throwsThrowable{audience.applaud();}//在抛出异常之后执行public
voidafterThrowing(Throwablethrowable){audience.demandRefund();}SUNWAH
//在抛出异常之后执行public
voidafterThrowing(Methodmethod,Object[]args,Objecttarget,Throwablethrowable){audience.demandRefund();}//injectedprivateAudienceaudience;public
voidsetAudience(Audienceaudience){this.audience=audience;}}SUNWAH
XML配置文件如下:<!--前通知、返回后通知和抛出后通知--><bean
id="audienceAdvice"
class="com.sunwah.training.spring.aop.AudienceAdvice"><property
name="audience"
ref="audience"
/></bean>SUNWAH周围通知周围通知相当于前通知、返回后通知、抛出后通知的结合。在Spring里,周围通知是由AOPAlliance的MethodInterceptor接口定义的。编写周围通知的好处:
•能以简洁的方式在一个方法里定义前通知和后通知。
•可以检查和修改被通知方法的返回值。
SUNWAH
以周围通知方式定义观众通知:packagecom.sunwah.training.spring.aop;importercept.MethodInterceptor;importercept.MethodInvocation;importcom.sunwah.training.spring.di.PerformanceException;/**
*
*
以周围通知方式定义观众通知
*
*/public
classAudienceAroundAdviceimplementsMethodInterceptor{SUNWAH
publicObjectinvoke(MethodInvocationinvocation)throwsThrowable{try{//在方法调用前执行audience.takeSeats();audience.turnOffCellPhones();//调用目标方法ObjectreturnValue=ceed();//在成功返回之后执行audience.applaud();returnreturnValue;}catch(PerformanceExceptionthrowable){//出现异常之后执行audience.demandRefund();throwthrowable;}}SUNWAH
//injectedprivateAudienceaudience;public
voidsetAudience(Audienceaudience){this.audience=audience;}}SUNWAH3.2.2定义切点和通知者连接点就是程序代码里切面通知可以被织入的地点。切点是以某种方式选择全部连接点的一个子集来定义通知应该被织入的地点。
SUNWAH声明正则表达式切点定义切点:<bean
id="performancePointcut"
class="org.springframework.aop.support.JdkRegexpMethodPointcut"><property
name="pattern"
value=".*perform"
/></bean>类JdkRegexpMethodPointcut实现正则表达式切点。pattern属性用于指定方法匹配所使用的切点模板。
SUNWAH
将切点与通知相关联:<bean
id="audienceAdvisor"
class="org.springframework.aop.support.DefaultPointcutAdvisor"><property
name="advice"
ref="audienceAdvice"
/><property
name="pointcut"
ref="performancePointcut"
/></bean>DefaultPointcutAdvisor类是个通知者类,它只是把通知关联到一个切点。
SUNWAH
联合切点与通知者:<bean
id="audienceAdvisor"class="org.springframework.aop.support.RegexpMethodPointcutAdvisor"><property
name="advice"
ref="audienceAdvice"
/><property
name="pattern"
value=".*perform"
/></bean>RegexpMethodPointcutAdvisor是个特殊的通知者类,可以在一个Bean里定义切点和通知者。
SUNWAH声明AspectJ切点定义切点:<bean
id="performancePointcut"class="org.springframework.aop.aspectj.AspectJExpressionPointcut"><property
name="expression"
value="execution(**.perform(..))"
/></bean>这里使用AspectJExpressionPointcut类而不是JdkRegexpMethodPointcut类。切点表达是被定义为expression属性的值。
SUNWAH
将切点与通知相关联:<bean
id="audienceAdvisor"
class="org.springframework.aop.support.DefaultPointcutAdvisor"><property
name="advice"
ref="audienceAdvice"
/><property
name="pointcut"
ref="performancePointcut"
/></bean>DefaultPointcutAdvisor类是个通知者类,它只是把通知关联到一个切点。
SUNWAH
联合切点与通知者:<bean
id="audienceAdvisor"class="org.springframework.aop.aspectj.AspectJExpressionPointcutAdvisor"><property
name="advice"
ref="audienceAdvice"
/><property
name="expression"
value="execution(**.perform(..))"
/></bean>AspectJExpressionPointcutAdvisor是个通知者类,用来同时定义切点和通知者。
SUNWAH3.2.3使用ProxyFactoryBean作为被通知者通知的Bean,它必须是被代理的。Spring的ProxyFactoryBean是个工厂Bean,用于生成一个代理,把一个或多个(通知)应用到Bean。target属性指明哪个Bean被代理;interceptorNames属性指明哪些通知者要应用于被代理的Bean;proxyInterfaces属性指明代理应该实现哪些接口。
SUNWAH
定义演出者Duke的目标Bean:<!--定义演出者Duke目标Bean--><bean
id="dukeTarget"
class="com.sunwah.training.spring.di.PoeticJuggler"><property
name="beanBags"
value="15"
/><property
name="poem"
ref="sonnet29"
/></bean>SUNWAH
定义演出者Duke的代理Bean:<!--定义演出者Duke代理Bean--><bean
id="duke"
class="org.springframework.aop.framework.ProxyFactoryBean"><property
name="target"
ref="dukeTarget"
/><!--<propertyname="interceptorNames"value="audienceAdvisor"/>--><property
name="interceptorNames"><list><value>audienceAdvisor</value></list></property><property
SUNWAH抽象ProxyFactoryBean定义观众参与演出者Steive的演出:<!--定义演出者Stevie目标Bean--><bean
id="stevieTarget"
class="com.sunwah.training.spring.di.PoeticJuggler"><property
name="beanBags"
value="18"
/><property
name="poem"
ref="sonnet29"
/></bean>SUNWAH
<!--定义演出者Stevie代理Bean--><bean
id="stevie"
class="org.springframework.aop.framework.ProxyFactoryBean"><property
name="target"
ref="stevieTarget"/><!--<propertyname="interceptorNames"value="audienceAdvisor"/>--><property
name="interceptorNames"><list><value>audienceAdvisor<
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 肾内分泌科护理工作总结
- 2025年全球及中国医用全自动凝血分析仪行业头部企业市场占有率及排名调研报告
- 2025年全球及中国企业级机械硬盘和固态硬盘行业头部企业市场占有率及排名调研报告
- 2025-2030全球3D晶体管行业调研及趋势分析报告
- 2025-2030全球立式不锈钢离心泵行业调研及趋势分析报告
- 2025-2030全球汽车电池试验箱行业调研及趋势分析报告
- 2025年全球及中国游戏人工智能NPC行业头部企业市场占有率及排名调研报告
- 2025-2030全球自动药敏分析仪行业调研及趋势分析报告
- 2025年全球及中国无线蓝牙肉类温度计行业头部企业市场占有率及排名调研报告
- 2025年全球及中国固定桥式坐标测量机行业头部企业市场占有率及排名调研报告
- 2025-2030年中国清真食品行业运行状况及投资发展前景预测报告
- 广东省茂名市电白区2024-2025学年七年级上学期期末质量监测生物学试卷(含答案)
- 《教育强国建设规划纲要(2024-2035年)》全文
- 山东省滨州市2024-2025学年高二上学期期末地理试题( 含答案)
- 2025年河南洛阳市孟津区引进研究生学历人才50人历年高频重点提升(共500题)附带答案详解
- 2025年度军人军事秘密保护保密协议与信息安全风险评估合同3篇
- 数字化转型中的职业能力重构
- 运用PDCA降低住院患者跌倒-坠床发生率
- 2025届高中数学一轮复习专练:椭圆(含解析)
- 立春气象与生活影响模板
- 中国服装零售行业发展环境、市场运行格局及前景研究报告-智研咨询(2025版)
评论
0/150
提交评论