Spring的核心机制及容器.ppt

上传人:牧羊曲112 文档编号:6520228 上传时间:2023-11-08 格式:PPT 页数:74 大小:380.50KB
返回 下载 相关 举报
Spring的核心机制及容器.ppt_第1页
第1页 / 共74页
Spring的核心机制及容器.ppt_第2页
第2页 / 共74页
Spring的核心机制及容器.ppt_第3页
第3页 / 共74页
Spring的核心机制及容器.ppt_第4页
第4页 / 共74页
Spring的核心机制及容器.ppt_第5页
第5页 / 共74页
点击查看更多>>
资源描述

《Spring的核心机制及容器.ppt》由会员分享,可在线阅读,更多相关《Spring的核心机制及容器.ppt(74页珍藏版)》请在三一办公上搜索。

1、第14章 Spring的核心机制及容器,14.1 Spring的核心机制,14.2 Spring容器,14.3 Bean中对集合的注入,14.4 两种后处理器,14.1 Spring的核心机制,14.1.1 依赖注入的概念新建一个Web Project,名称为Spring_DI,为其添加Spring核心类库,步骤见13.2节的第2步。创建包“org.interfaces”,在该包中新建Person接口,代码如下:package org.interfaces;/*定义Person接口*/public interface Person/接口中定义一个吃食物方法public void eatFood

2、();继续在该包中定义Food接口,代码如下:package org.interfaces;/*定义Food接口*/public interface Food/在接口中定义一个吃的方法,返回吃的东西public String eat();,14.1.1 依赖注入的概念,创建包“”,在该包中定义Person的实现类Man,代码如下:package org.interfaces.impl;import org.interfaces.Food;import org.interfaces.Person;/*Person接口的具体实现类*/public class Man implements Pers

3、on/定义Food接口私有属性,面向Food接口编程,而不是具体的实现类private Food food;/构建 setter方法,必须要有,后面会讲解为什么public void setFood(Food food)this.food=food;/实现Person接口eatFood方法public void eatFood()System.out.println(food.eat();,14.1.1 依赖注入的概念,定义Food的一个实现类Apple,代码如下:package org.interfaces.impl;import org.interfaces.Food;public cla

4、ss Apple implements Food public String eat()return 正在吃苹果.;在src下编写Spring的配置文件config.xml,使用Spring的配置文件将Person实例和Food实例组织在一起,配置内容。,14.1.1 依赖注入的概念,下面就可以编写测试类了,代码如下:package org.test;import org.interfaces.Person;import org.springframework.context.ApplicationContext;import org.springframework.context.suppo

5、rt.FileSystemXmlApplicationContext;public class Test public static void main(String args)/创建ApplicationContext对象,参数为配置文件放置的位置 ApplicationContext context=new FileSystemXmlApplicationContext(/WebRoot/WEB-INF/classes/config.xml);/通过Person bean的id来获取bean实例,面向接口编程,因此此处强制类型转换为接口类型 Person p=(Person)context

6、.getBean(man);/直接执行Person的eatFood()方法 p.eatFood();,14.1.1 依赖注入的概念,运行主程序,输出结果,代码如下:正在吃苹果.在主程序中,调用了Person的eatFood()方法,该方法的方法体内需要使用Food的实例,按照通常的方式,在Person实例的eatFood()方法中,应该这样实现:/创建Food实例food=new Apple();/获得Food实例的eat方法返回值System.out.println(food.eat();,14.1.1 依赖注入的概念,如果需要改写Food的实现类,或者提供另一个实现类给Person实例使用

7、,Person接口和Man实现类都无须改变,只需提供另一个Food的实现,然后对配置文件进行简单的修改即可。例如,我们现在新建另一个Food的实现类Orange,代码如下:package org.interfaces.impl;import org.interfaces.Food;/*定义Orange类,实现Food接口*/public class Orange implements Food/*实现接口吃的方法*/public String eat()return 正在吃橘子.;,14.1.1 依赖注入的概念,修改配置文件config.xml,增加orange的Bean,代码如下:该行重新定

8、义了一个Food的实现:orange,然后修改man的bean配置,将原来传入apple的地方改为传入orange。也就是将:改成:再次运行主程序,输出结果如下:正在吃橘子.,14.1.2 依赖注入的两种方式,前面讲解了依赖注入的概念,本节将介绍依赖注入的两种方式:set注入及构造注入。其中,set注入已经在HelloWorld程序中及上面的程序中应用过了,使用方法非常简单,需要为被注入的属性或类构建setter方法,例如在HelloWorld.java中:package org.model;public class HelloWorld private String message;publ

9、ic String getMessage()return message;public void setMessage(String message)this.message=message;,14.1.2 依赖注入的两种方式,然后通过配置文件的Bean来为其注入值:Hello World!,14.1.2 依赖注入的两种方式,这样设置后就可以调用HelloWorld的对象来调用getter方法,获取为message设置的值了。同样地,在Man.java中:package org.interfaces.impl;import org.interfaces.Food;import org.inte

10、rfaces.Person;/*Person接口的具体实现类*/public class Man implements Person/定义Food接口私有属性,面向Food接口编程,而不是具体的实现类private Food food;/设置依赖注入所需的setter方法,这就解释了为什么必须有setter方法 public void setFood(Food food)this.food=food;/实现Person接口eatFood方法public void eatFood()System.out.println(food.eat();,14.1.2 依赖注入的两种方式,通过配置文件对fo

11、od进行依赖注入:构造注入,是指在接受注入的类中定义一个构造方法,并在构造方法的参数中定义需要注入的元素。下面就把HelloWorld实例修改为应用构造注入来为元素设值。具体步骤是:首先,修改HelloWorld.java类,在该类中增加一个构造方法,然后再修改配置文件config.xml,最后测试程序。HelloWorld.java类修改为:package org.model;public class HelloWorld private String message;public HelloWorld(String message)this.message=message;public S

12、tring getMessage()return message;,14.1.2 依赖注入的两种方式,config.xml修改为:HelloWorld,14.1.2 依赖注入的两种方式,其中,“constructor-arg”用来表示通过构造方式来进行依赖注入,“index=0”表示构造方法中的第一个参数,如果只有一个参数,可以省略不写,如果有多个参数,就直接重复配置“constructor-arg”即可,不过要改变“index”的值,例如,如果在“HelloWorld”类中还有一个参数“mess”,并且通过构造方法为其注入值:public HelloWorld(String message,

13、String mess)this.message=message;this.mess=mess;那么,只需在配置文件config.xml中加上一个“constructor-arg”:HelloYabber,14.1.3 两种注入方式的比较,在开发过程中,set注入和构造注入都是会经常用到的,这两种依赖注入的方式并没有绝对的好坏,只是使用的场合有所不同而已。使用构造注入可以在构建对象的同时一并完成依赖关系的建立,所以,如果要建立的对象的关系很多,使用构造注入就会在构造方法上留下很多的参数,是非常不易阅读的,这时建议使用set注入。然而,用set注入由于提供了setXx()方法,所以不能保证相关的

14、数据在执行时不被更改设定,因此,如果想要让一些数据变为只读或私有,使用构造注入会是个很好的选择。,14.2 Spring容器,14.2.1 Bean的定义Bean是描述Java的软件组件模型,其定义在Spring配置文件的根元素下,元素是元素的子元素,在根元素下可以包含多个子元素。每个可以完成一个简单的功能,也可以完成一个复杂的功能,之间可以互相协同工作,完成复杂的关系。,14.2.2 Bean的基本属性,在HelloWorld实例中,config.xml中的Bean的配置如下:Hello Yabber!在Bean中有一个id属性及class属性,这个id唯一标识了该Bean。在配置文件中,不

15、能有重复的Bean的id,因为在代码中通过BeanFactory或ApplicationContext来获取Bean的实例时,都要用它来作为唯一索引:HelloWorld helloWorld=(HelloWorld)ac.getBean(HelloWorld);,14.2.2 Bean的基本属性,1Bean的id属性为Bean指定别名可以用name属性来完成,如果需要为Bean指定多个别名,可以在name属性中使用逗号(,)、分号(;)或空格来分隔多个别名,在程序中可以通过任意一个别名访问该Bean实例。例如,id为“HelloWorld”的Bean,其别名为:Hello Yabber!则在

16、程序中可以利用“a”、“b”、“c”任意一个来获取Bean的实例:HelloWorld helloWorld=(HelloWorld)ac.getBean(a);或HelloWorld helloWorld=(HelloWorld)ac.getBean(b);或HelloWorld helloWorld=(HelloWorld)ac.getBean(c);以上三种方法均可完成Bean实例的获取。,14.2.2 Bean的基本属性,2Bean的class属性可以看出,每个Bean都会指定class属性,class属性指明了Bean的来源,即Bean的实际路径,注意,这里要写出完整的包名+类名。例

17、如:class属性非常简单,这里就不过多介绍了。3Bean的scope属性scope属性用于指定Bean的作用域,Spring支持5种作用域,这5种作用域如下:singleton:单例模式,当定义该模式时,在容器分配Bean的时候,它总是返回同一个实例。该模式是默认的,即不定义scope时的模式。prototype:原型模式,即每次通过容器的getBean方法获取Bean的实例时,都将产生信息的Bean实例。,14.2.2 Bean的基本属性,request:对于每次HTTP请求中,使用request定义的Bean都将产生一个新实例,即每次HTTP请求将会产生不同的Bean实例。只有在Web应

18、用中使用Spring时,该作用域有效。session:对于每次HTTP Session请求中,使用session定义的Bean都将产生一个新实例,即每次HTTP Session请求将会产生不同的Bean实例。只有在Web应用中使用Spring时,该作用域有效。global session:每个全局的Http Session对应一个Bean实例。典型情况下,仅在使用portlet context的时候有效。只有在Web应用中使用Spring时,该作用域才有效。,14.2.2 Bean的基本属性,比较常用的是前两种作用域,即singleton及prototype。下面举例说明这两种作用域的差别。仍

19、然是对HelloWorld程序进行修改,在配置文件config.xml中这样配置:在“HelloWorld1”Bean中没有定义“scope”属性,即默认的“singleton”单例模式。“HelloWorld2”Bean中指定作用域为“prototype”,即原型模式。HelloWorld.java类不变,编写测试类代码。,14.2.2 Bean的基本属性,运行该应用程序,控制台输出如图14.1所示。从输出内容可以发现,应用单例模式得到的Bean实例永远是同一实例,而原型模式则是不同的实例。,图14.1 控制台输出,14.2.2 Bean的基本属性,4Bean的property在Spring

20、的依赖注入中,是应用Bean的子元素来为属性进行设值的:Hello World!如果要为属性设置“null”,有两种方法。第一种直接用value元素指定:null,14.2.2 Bean的基本属性,第二种方法直接用:,14.2.3 Bean的生命周期,1Bean的定义Bean的定义在前面的实例中已经应用很多了,从基本的HelloWorld程序中就可以基本看出Bean的定义,这里就不再列举其定义形式,但值得一提的是,在一个大的应用中,会有很多的Bean需要在配置文件中定义,这样配置文件就会很大,变得不易阅读及维护,这时可以把相关的Bean放置在一个配置文件中,创建多个配置文件。2Bean的初始化

21、在Spring中,Bean完成全部属性的设置后,Spring 中的bean的初始化回调有两种方法,一种是在配置文件中声明“init-method=init”,然后在HelloWorld类中写一个init()方法来初始化;另一种是实现InitializingBean 接口,然后覆盖其afterPropertiesSet()方法。知道了初始化过程中会应用这两种方法,就可以在Bean的初始化过程中让其执行特定行为。,14.2.3 Bean的生命周期,下面介绍这两种方法的使用方式。第一种方式如下:(1)在HelloWorld类中增加一个init()方法。代码如下:package org.model;p

22、ublic class HelloWorld private String message;public String getMessage()return message;public void setMessage(String message)this.message=message;public void init()/利用该方法修改message的值this.setMessage(Hello Yabber);,14.2.3 Bean的生命周期,(2)修改配置文件config.xml,指定Bean中要初始化的方法为init(),代码如下:HelloWorld,14.2.3 Bean的生

23、命周期,(3)编写测试类,输出HelloWorld中message的值,代码如下:package org.test;import org.model.HelloWorld;import org.springframework.context.ApplicationContext;import org.springframework.context.support.FileSystemXmlApplicationContext;public class Test public static void main(String args)ApplicationContext ac=new FileS

24、ystemXmlApplicationContext(/WebRoot/WEB-INF/classes/config.xml);HelloWorld helloWorld=(HelloWorld)ac.getBean(HelloWorld);System.out.println(helloWorld.getMessage();,14.2.3 Bean的生命周期,运行该程序,控制台输出如图14.2所示。可以发现,初始化方法的调用是在Bean初始化的后期执行的,改变了message的赋值,故输出为“Hello Yabber”。,图14.2 控制台输出,14.2.3 Bean的生命周期,第二种方式,

25、实现InitializingBean接口,并覆盖其“afterPropertiesSet()”方法。(1)修改HelloWorld.java,让其实现InitializingBean接口,并覆盖其“afterPropertiesSet()”方法。代码实现为:package org.model;import org.springframework.beans.factory.InitializingBean;public class HelloWorld implements InitializingBeanprivate String message;public String getMess

26、age()return message;public void setMessage(String message)this.message=message;public void afterPropertiesSet()throws Exception this.setMessage(Hello Yabber);,14.2.3 Bean的生命周期,(2)修改config.xml配置文件,代码如下:HelloWorld,14.2.3 Bean的生命周期,3Bean的应用Bean的应用非常简单,在Spring中有两种使用Bean的方式。第一种,使用BeanFactory:/在ClassPath下

27、寻找,由于配置文件就是放在ClassPath下,故可以直接找到ClassPathResource res=new ClassPathResource(config.xml);XmlBeanFactory factory=new XmlBeanFactory(res);HelloWorld helloWorld=(HelloWorld)factory.getBean(HelloWorld);System.out.println(helloWorld.getMessage();第二种,使用ApplicationContext:ApplicationContext ac=new FileSystem

28、XmlApplicationContext(/WebRoot/WEB-INF/classes/config.xml);HelloWorld helloWorld=(HelloWorld)ac.getBean(HelloWorld);System.out.println(helloWorld.getMessage();,14.2.3 Bean的生命周期,4Bean的销毁首先介绍第一种方式。(1)在HelloWorld类中增加一个cleanup()方法。代码如下:package org.model;public class HelloWorldDestroyprivate String messa

29、ge;public String getMessage()return message;public void setMessage(String message)this.message=message;public void cleanup()this.setMessage(HelloWorld!);System.out.println(销毁之前要调用!);,14.2.3 Bean的生命周期,(2)修改config.xml配置文件,代码如下:HelloWorld,14.2.3 Bean的生命周期,(3)编写测试类,输出message的值,代码如下:package org.test;impo

30、rt org.model.HelloWorldDestroy;import org.springframework.context.support.AbstractApplicationContext;import org.springframework.context.support.FileSystemXmlApplicationContext;public class Test public static void main(String args)AbstractApplicationContext ac=new FileSystemXmlApplicationContext(/Web

31、Root/WEB-INF/classes/config.xml);HelloWorldDestroy helloWorld=(HelloWorldDestroy)ac.getBean(HelloWorld);System.out.println(helloWorld.getMessage();/为Spring容器注册关闭钩子,程序将会在推出JVM之前关闭Spring容器ac.registerShutdownHook();,14.2.3 Bean的生命周期,运行程序,控制台输出结果如图14.3所示。,图14.3 控制台输出结果,14.2.3 Bean的生命周期,第二种方式,实现Disposabl

32、eBean接口,并覆盖其destroy()方法。(1)修改HelloWorldDestroy.java,让其实现DisposableBean接口,并覆盖其“destroy()”方法。代码实现为:package org.model;import org.springframework.beans.factory.DisposableBean;public class HelloWorldDestroy implements DisposableBeanprivate String message;public String getMessage()return message;public vo

33、id setMessage(String message)this.message=message;public void destroy()throws Exception System.out.println(该句在销毁之前要显示!);,14.2.3 Bean的生命周期,(2)配置文件config.xml修改为:HelloWorld,14.2.4 Bean的管理,1BeanFactory在Spring中有几种BeanFactory的实现,其中最常用的是。它根据XML文件中的定义装载Bean。要创建XmlBeanFactory,需要传递一个ClassPathResource对象给构造方法。例

34、如,下面的代码片段获取一个BeanFactory对象:/在ClassPath下寻找,由于配置文件就是放在ClassPath下,故可以直接找到ClassPathResource res=new ClassPathResource(config.xml);BeanFactory factory=new XmlBeanFactory(res);为了从BeanFactory得到Bean,只要简单地调用getBean()方法,把需要的Bean的名字当做参数传递进去就行了。由于得到的是Object类型,所以要进行强制类型转化:HelloWorld helloWorld=(HelloWorld)factor

35、y.getBean(HelloWorld);,14.2.4 Bean的管理,2ApplicationContextBeanFactory对简单应用来说已经很好了,但是为了获得Spring框架的强大功能,需要使用Spring更加高级的容器ApplicationContext(应用上下文)。表面上看,ApplicationContext和BeanFactory差不多,两者都是载入Bean的定义信息,装配Bean,根据需要分发Bean,但是ApplicationContext提供了更多的功能:应用上下文提供了文本信息解析工具,包括对国际化的支持。应用上下文提供了载入文本资源的通用方法,如载入图片。应

36、用上下文可以向注册为监听器的Bean发送事件。,14.2.4 Bean的管理,在ApplicationContext的诸多实现中,有三个常用的实现:ClassPathXmlApplicationContext:从类路径中的XML文件载入上下文定义信息,把上下文定义文件当成类路径资源。FileSystemXmlApplicationContext:从文件系统中的XML文件载入上下文定义信息。XmlWebApplicationContext:从Web系统中的XML文件载入上下文定义信息。例如:ApplicationContext context=new FileSystemXmlApplicati

37、onContext(c:/server.xml);ApplicationContext context=new ClassPathApplicationContext(server.xml);ApplicationContext context=WebApplicationContextUtils.getWebApplicationContext(request.getSession().getServletContext();FileSystemXmlApplicationContext和ClassPathXmlApplicationContext的区别是:FileSystemXmlAppl

38、icationContext只能在指定的路径中寻找server.xml 文件,而ClassPathXml ApplicationContext可以在整个类路径中寻找foo.xml。,14.2.5 Bean的依赖关系,Bean的依赖关系是指当为一个Bean的属性赋值时要应用到另外的Bean,这种情况也称Bean的引用。例如,有这样的一个类DateClass.java:package org.model;import java.util.Date;public class DateClass private Date date;public Date getDate()return date;pu

39、blic void setDate(Date date)this.date=date;,14.2.5 Bean的依赖关系,在配置文件中为其注入“date”值时,引用了其他Bean,代码为:,14.2.5 Bean的依赖关系,编辑测试程序Test.java:package org.test;import org.model.DateClass;import org.springframework.context.ApplicationContext;import org.springframework.context.support.FileSystemXmlApplicationContext

40、;public class Test public static void main(Stringargs)ApplicationContext ac=new FileSystemXmlApplicationContext(/WebRoot/WEB-INF/classes/config.xml);DateClass dc=(DateClass)ac.getBean(getDate);System.out.println(dc.getDate();,14.2.5 Bean的依赖关系,运行程序,控制台输出如图14.4所示。控制台打印出了本机的当前时间,在“getDate”的Bean中引用了“d”B

41、ean,也就为DateClass类中的属性“date”赋值为“d”Bean,即该Bean的对象,故打印出了当前时间。,图14.4 控制台输出结果,14.2.5 Bean的依赖关系,从上例可以看出,Spring中是用“ref”来指定依赖关系的,用“ref”指定依赖关系有3中方法:local、bean和parent。前面的例子中应用了“local”方法指定,其实也可以应用其他两种方法,例如上例的配置文件若应用“bean”可以修改为:,14.2.5 Bean的依赖关系,还可以直接应用property中的ref属性,例如上例可以修改为:,14.2.6 Bean的自动装配,1byName模式使用byNa

42、me模式在Bean的初始化时会通过Bean的属性名字进行自动装配,在Spring的配置文件中,查找一个与将要装配的属性同样名字的Bean。例如,DateClass.java为:package org.model;import java.util.Date;public class DateClass private Date date;public Date getDate()return date;public void setDate(Date date)this.date=date;,14.2.6 Bean的自动装配,配置文件config.xml中可以用“byName”自动装配模式来为属

43、性“date”自动装配值,配置文件可以配置为:,14.2.6 Bean的自动装配,可以发现,在“getDate”Bean中没有为属性指定值,但指定了“autowire=byName”。编辑测试类Test.java:package org.test;import org.model.DateClass;import org.springframework.context.ApplicationContext;import org.springframework.context.support.FileSystemXmlApplicationContext;public class Test pu

44、blic static void main(Stringargs)ApplicationContext ac=new FileSystemXmlApplicationContext(/WebRoot/WEB-INF/classes/config.xml);DateClass dc=(DateClass)ac.getBean(getDate);System.out.println(dc.getDate();运行后查看结果,输出为:Wed Jul 28 16:56:40 CST 2009,14.2.6 Bean的自动装配,2使用byType模式byType模式指如果配置文件中正好有一个与属性类型一

45、样的Bean,就自动装配这个属性,如果有多于一个这样的Bean,就抛出一个异常。例如在上例中,DateClass类的属性date为“Date”类型,而在配置文件中也有一个“Date”类型的Bean,这时若配置了自动装配的byType模式,就会自动装配DateClass类中的属性date值。例如,把上例的配置文件稍微修改,其他的不改变:,14.2.6 Bean的自动装配,3使用constructor模式constructor模式指的是根据构造方法的参数进行自动装配。例如,把DateClass.java修改为:package org.model;import java.util.Date;publ

46、ic class DateClass private Date date;public DateClass(Date date)this.date=date;public Date getDate()return date;public void setDate(Date date)this.date=date;,14.2.6 Bean的自动装配,配置文件config.xml修改为:,14.2.6 Bean的自动装配,4使用autodetect模式autodetect模式指的是通过检查类的内部来选择使用constructor或byType模式。例如,把使用constructor模式的实例的配置

47、文件修改为:,14.2.6 Bean的自动装配,5使用no模式使用no模式就是不使用自动装配,这时为属性赋值就必须通过ref来引用其他Bean。例如,DateClass.java修改为:package org.model;import java.util.Date;public class DateClass private Date date;public DateClass(Date date)this.date=date;public Date getDate()return date;public void setDate(Date date)this.date=date;,14.2.

48、6 Bean的自动装配,配置文件修改为:,14.3 Bean中对集合的注入,14.3.1 对list的注入对list集合的注入非常简单,如果类中有list类型的属性,在为其依赖注入值的时候就需要在配置文件中的元素下应用其子元素。下面举例说明。创建类ListBean.java,其有一个List类型的属性,代码如下:package org.model;import java.util.List;public class ListBean private List list;public List getList()return list;public void setList(List list)

49、this.list=list;,14.3.1 对list的注入,配置文件中Bean的配置为:javac+php,14.3.1 对list的注入,编写测试类,对ListBean类的“list”属性进行输入,测试是否注入成功。package org.test;import java.util.Iterator;import java.util.List;import org.model.ListBean;import org.springframework.context.ApplicationContext;import org.springframework.context.support.F

50、ileSystemXmlApplicationContext;public class Test public static void main(Stringargs)ApplicationContext ac=new FileSystemXmlApplicationContext(/WebRoot/WEB-INF/classes/config.xml);ListBean listbean=(ListBean)ac.getBean(listBean);List l=listbean.getList();System.out.println(l);运行程序,控制台信息为:java,c+,php,

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 生活休闲 > 在线阅读


备案号:宁ICP备20000045号-2

经营许可证:宁B2-20210002

宁公网安备 64010402000987号