已阅读5页,还剩18页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
框架学习之Spring 第二节 采用Spring管理Bean和依赖注入 1.实例化spring容器 和 从容器获取Bean对象实例化Spring容器常用的两种方式:方法一:在类路径下寻找配置文件来实例化容器 推荐使用ApplicationContext ctx = new ClassPathXmlApplicationContext(new Stringbeans.xml);方法二:在文件系统路径下寻找配置文件来实例化容器 这种方式可以在开发阶段使用ApplicationContext ctx = new FileSystemXmlApplicationContext(new String“d:beans.xml“);Spring的配置文件可以指定多个,可以通过String数组传入。当spring容器启动后,因为spring容器可以管理bean对象的创建,销毁等生命周期,所以我们只需从容器直接获取Bean对象就行,而不用编写一句代码来创建bean对象。从容器获取bean对象的代码如下:ApplicationContext ctx = new ClassPathXmlApplicationContext(“beans.xml”);OrderService service = (OrderService)ctx.getBean(personService);2.Spring实例化Bean的三种方式以下是三种方式的例子:1.使用类构造器实例化 默认的类构造器2.使用静态工厂方法实例化public class OrderFactory public static OrderServiceBean createOrder() / 注意这里的这个方法是 static 的! return new OrderServiceBean(); 3.使用实例工厂方法实例化:public class OrderFactory public OrderServiceBean createOrder() return new OrderServiceBean(); 3.Bean的生命周期 (Bean的作用域)bean的scope 属性The scope of this bean: typically singleton (one shared instance, which will be returned by all calls to getBean with the given id), or prototype (independent instance resulting from each call to getBean). Default is singleton. Singletons are most commonly used, and are ideal for multi- threaded service objects. Further scopes, such as request or session, might be supported by extended bean factories (e.g. in a web environment). Note: This attribute will not be inherited by child bean definitions. Hence, it needs to be specified per concrete bean definition. Inner bean definitions inherit the singleton status of their containing bean definition, unless explicitly specified: The inner bean will be a singleton if the containing bean is a singleton, and a prototype if the containing bean has any other scope.singleton 单例 eg:在每个Spring IoC容器中一个bean定义只有一个对象实例。请注意Spring的singleton bean概念与“四人帮”(GoF)模式一书中定义的Singleton模式是完全不同的。经典的GoF Singleton模式中所谓的对象范围是指在每一个ClassLoader中指定class创建的实例有且仅有一个。把Spring的singleton作用域描述成一个container对应一个bean实例最为贴切。亦即,假如在单个Spring容器内定义了某个指定class的bean,那么Spring容器将会创建一个且仅有一个由该bean定义指定的类实例。默认情况下会在容器启动时初始化bean,但我们可以指定Bean节点的lazy-init=“true”来延迟初始化bean,这时候,只有第一次获取bean会才初始化bean。如:如果想对所有bean都应用延迟初始化,可以在根节点beans设置default-lazy-init=“true“,如下:.prototype原型 每次从容器获取bean都是新的对象。对于prototype作用域的bean,有一点非常重要,那就是Spring不能对一个prototype bean的整个生命周期负责:容器在初始化、配置、装饰或者是 装配完一个prototype实例后,将它交给客户端,随后就对该prototype实例不闻不问了。不管何种作用域,容器都会调用所有对象的初始化生命周期回调方法。 但对prototype而言,任何配置好的析构生命周期回调方法都将不会被调用。清除prototype作用域的对象并释放任何prototype bean所持有的昂贵资源, 都是客户端代码的职责。(让Spring容器释放被prototype作用域bean占用资源的一种可行方式是,通过使用bean的后置处理器,该处理器持有要被清除的bean的引用。) 以下的三种scope只是在web应用中才可以使用.request .session .global session使用这三种配置之前要先初始化Web配置RequestContextListener和RequestContextFilter两个类做的都是同样的工作: 将HTTP request对象绑定到为该请求提供服务的Thread。 这使得具有request和session作用域的bean能够在后面的调用链中被访问到。指定Bean的初始化方法和销毁方法Spring提供了几个标志接口(marker interface),这些接口用来改变容器中bean的行为;它们包括InitializingBean和DisposableBean。 现这两个接口的bean在初始化和析构时容器会调用前者的afterPropertiesSet()方法,以及后者的destroy()方法。 Spring在内部使用BeanPostProcessor实现来处理它能找到的任何标志接口并调用相应的方法。 如果你需要自定义特性或者生命周期行为,你可以实现自己的 BeanPostProcessor。 初始化回调和析构回调: 测试:bean对象:package com.yinger.service.impl;public class PersonServiceBean implements com.yinger.service.PersonService /构造器 public PersonServiceBean() System.out.println(instance me); /save方法 public void save() System.out.println(save); /初始化方法,这个方法是类被实例化了之后就会执行的! public void init() System.out.println(init); /销毁方法 public void destroy() System.out.println(destroy); JUnit Test:package com.yinger.test;import org.junit.BeforeClass;import org.junit.Test;import org.springframework.context.support.AbstractApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;import com.yinger.service.PersonService;public class SpringTest BeforeClass public static void setUpBeforeClass() throws Exception Test /创建的单元测试 public void testSave() AbstractApplicationContext ctx = new ClassPathXmlApplicationContext(beans.xml); System.out.println(-); PersonService ps = (PersonService)ctx.getBean(personService); ps.save(); ctx.close(); /有了这一句才会有destroy方法的调用 beans.xml 设置:如果lazy-init(默认是default,也就是false)没有设置,或者设置为default或者false 那么结果是:log4j:WARN No appenders could be found for logger (org.springframework.context.support.ClassPathXmlApplicationContext).log4j:WARN Please initialize the log4j system properly.instance meinit-savedestroy反之,如果设置为true,结果是:log4j:WARN No appenders could be found for logger (org.springframework.context.support.ClassPathXmlApplicationContext).log4j:WARN Please initialize the log4j system properly.-instance meinitsavedestroy修改测试代码: Test public void testSave() AbstractApplicationContext ctx = new ClassPathXmlApplicationContext(beans.xml);/ System.out.println(-); PersonService ps = (PersonService)ctx.getBean(personService); PersonService ps1 = (PersonService)ctx.getBean(personService); System.out.println(ps=ps1);/ ps.save(); ctx.close(); 重新测试:log4j:WARN No appenders could be found for logger (org.springframework.context.support.ClassPathXmlApplicationContext).log4j:WARN Please initialize the log4j system properly.instance meinittruedestroy在scope为singleton时,每次使用getBean得到的都是同一个bean,同一个对象修改bean中的scope属性:scope=prototype测试结果:log4j:WARN No appenders could be found for logger (org.springframework.context.support.ClassPathXmlApplicationContext).log4j:WARN Please initialize the log4j system properly.instance meinitinstance meinitfalse在scope为prototype时,每次得到的bean对象都是不同的,从上面可以看出实例化了两个对象,最终的比较是false4.依赖注入来自Spring参考文档:依赖注入(DI)背后的基本原理是对象之间的依赖关系(即一起工作的其它对象)只会通过以下几种方式来实现:构造器的参数、工厂方法的参数,或给由构造函数或者工厂方法创建的对象设置属性。因此,容器的工作就是创建bean时注入那些依赖关系。相对于由bean自己来控制其实例化、直接在构造器中指定依赖关系或者类似服务定位器(Service Locator)模式这3种自主控制依赖关系注入的方法来说,控制从根本上发生了倒转,这也正是控制反转(Inversion of Control, IoC) 名字的由来。 (1)基本类型的注入:基本类型对象注入: /构造器注入 /属性setter方法注入注入其他bean:方式一 方式二(使用内部bean,但该bean不能被其他bean使用) 测试 构造器和setter 方式注入:新建一个DAO的接口:package com.yinger.dao;public interface PersonDao public void save(); 新建一个接口的实现类:package com.yinger.dao.impl;import com.yinger.dao.PersonDao;public class PersonDaoBean implements PersonDao public void save() System.out.println(PersonDaoBean.save(); 修改原有的PersonServiceBean,添加两个字段:package com.yinger.service.impl;import com.yinger.dao.PersonDao;import com.yinger.service.PersonService;public class PersonServiceBean implements PersonService private PersonDao pDao;/这样设计就实现了业务层和数据层的彻底解耦 private String name; /默认的构造器 public PersonServiceBean() System.out.println(instance me); /带参数的构造器 public PersonServiceBean(PersonDao pDao) this.pDao=pDao; /带参数的构造器 public PersonServiceBean(PersonDao pDao,String name) this.pDao=pDao; =name; /save方法 public void save() / System.out.println(save); pDao.save(); System.out.println(this.getName(); /初始化方法,这个方法是类被实例化了之后就会执行的! public void init() System.out.println(init); /销毁方法 public void destroy() System.out.println(destroy); public String getName() return name; public void setName(String name) = name; 修改beans.xml: 新增一个测试方法: Test public void testInjection() AbstractApplicationContext ctx = new ClassPathXmlApplicationContext(beans.xml); System.out.println(-); PersonService ps = (PersonService)ctx.getBean(personService); ps.save(); ctx.close(); 测试结果:log4j:WARN No appenders could be found for logger (org.springframework.context.support.ClassPathXmlApplicationContext).log4j:WARN Please initialize the log4j system properly.-PersonDaoBean.save()name如果在beans.xml中再添加一句:重新测试,结果是:log4j:WARN No appenders could be found for logger (org.springframework.context.support.ClassPathXmlApplicationContext).log4j:WARN Please initialize the log4j system properly.-PersonDaoBean.save()name2(2)集合类型的注入:集合类型的装配:public class OrderServiceBean private Set sets = new HashSet(); private List lists = new ArrayList(); private Properties properties = new Properties(); private Map maps = new HashMap(); ./这里省略属性的getter和setter方法XML配置: lihuoming set sss 补充:Spring对泛型的支持(3)三种依赖注入的方式 和 两种装配方式:使用构造器注入使用属性setter方法注入:通过调用无参构造器或无参static工厂方法实例化bean之后,调用该bean的setter方法,即可实现基于setter的DI。 Spring开发团队提倡使用setter注入。而且setter DI在以后的某个时候还可将实例重新配置(或重新注入) 使用Field注入(用于注解方式)处理bean依赖关系通常按以下步骤进行: 根据定义bean的配置(文件)创建并初始化BeanFactory实例(大部份的Spring用户使用支持XML格式配置文件的BeanFactory或ApplicationContext实现)。每个bean的依赖将以属性、构造器参数、或静态工厂方法参数的形式出现。当这些bean被实际创建时,这些依赖也将会提供给该bean。每个属性或构造器参数既可以是一个实际的值,也可以是对该容器中另一个bean的引用。每个指定的属性或构造器参数值必须能够被转换成特定的格式或构造参数所需的类型。默认情况下,Spring会以String类型提供值转换成各种内置类型, 比如int、long、String、boolean等。在或元素内部还可以使用ref元素。该元素用来将bean中指定属性的值设置为对容器中的另外一个bean的引用。注意:内部bean中的scope标记及id或name属性将被忽略。内部bean总是匿名的且它们总是prototype模式的。同时将内部bean注入到包含该内部bean之外的bean是不可能的。 注入依赖对象可以采用手工装配或自动装配,在实际应用中建议使用手工装配,因为自动装配会产生未知情况,开发人员无法预见最终的装配结果。1.手工装配依赖对象2.自动装配依赖对象手工装配手工装配依赖对象,在这种方式中又有两种编程方式1. 在xml配置文件中,通过在bean节点下配置,如/构造器注入/属性setter方法注入2. 在java代码中使用Autowired或Resource注解方式进行装配。但我们需要在xml配置文件中配置以下信息: 这个配置隐式注册了多个对注释进行解析处理的处理器:AutowiredAnnotationBeanPostProcessor,CommonAnnotationBeanPostProcessor,PersistenceAnnotationBeanPostProcessor,RequiredAnnotationBeanPostProcessor注: Resource注解在spring安装目录的libj2eecommon-annotations.jar* 注解方式的讲解在java代码中使用Autowired或Resource注解方式进行装配,这两个注解的区别是:Autowired 默认按类型装配,Resource默认按名称装配,当找不到与名称匹配的bean才会按类型装配。 Autowired private PersonDao personDao;/用于字段上 Autowired public void setOrderDao(OrderDao orderDao) /用于属性的setter方法上 this.orderDao = orderDao; Autowired注解是按类型装配依赖对象,默认情况下它要求依赖对象必须存在,如果允许null值,可以设置它required属性为false。如果我们想使用按名称装配,可以结合Qualifier注解一起使用。如下: Autowired Qualifier(personDaoBean) private PersonDao personDao;注:Autowired 注解可以使用在很多地方,包括了 集合类型,Map,来自ApplicationContext的特殊类型的所有 beans等等特殊的情况:多个构造器虽然当 一个类只有一个连接构造器时它将被标记为 required, 但是还是可以标记多个构造器的。在这种情况下,每一个构造器都有可能被认为是连接构造器, Spring 将会把依赖关系能够满足的构造器认为是greediest 的构造器测试:Autowired注解 如果两个构造器都使用了该注解会报错!所以,在多个构造器的情况下,要多多考虑新建一个PersonServiceBean2类:其中有三处使用了 Autowired注解 ,只要其中一个位置包含了注解就行测试时package com.yinger.service.impl;import org.springframework.beans.factory.annotation.Autowired;import com.yinger.dao.PersonDao;import com.yinger.service.PersonService;public class PersonServiceBean2 implements PersonService /Autowired默认是按照类型来装配,这里是放在字段上 Autowired private PersonDao pDao;/这样设计就实现了业务层和数据层的彻底解耦 /默认的构造器 public PersonServiceBean2() System.out.println(instance me); /带参数的构造器 Autowired /放在构造方法上 public PersonServiceBean2(PersonDao pDao) this.pDao=pDao; /save方法 public void save() pDao.save(); /初始化方法,这个方法是类被实例化了之后就会执行的! public void init() System.out.println(init); /销毁方法 public void destroy() System.out.println(destroy); public PersonDao getpDao() return pDao; Autowired /放在属性的setter上 public void setpDao(PersonDao pDao) this.pDao = pDao; beans.xml: 测试方法: Test /用于测试依赖注入的方法 public void testInjection() AbstractApplicationContext ctx = new ClassPathXmlApplicationContext(beans.xml); System.out.println(-); PersonService ps = (PersonService)ctx.getBean(personService2); ps.save(); ctx.close(); 测试结果:log4j:WARN No appenders could be found for logger (org.springframework.context.support.ClassPathXmlApplicationContext).log4j:WARN Please initialize the log4j system properly.-PersonDaoBean.save()从结果中可以看出,PersonDao是注入进去了!还有一个要注意,按照类型查找,并不是类型一定要完全吻合,可以是属性(字段,方法参数)的实现类(如果以上的是接口),上面的实例就是一个例子Resource注解和Autowired一样,也可以标注在字段或属性的setter方法上,但它默认按名称装配。名称可以通过Resource的name属性指定,如果没有指定name属性,当注解标注在字段上,即默认取字段的名称作为bean名称寻找依赖对象,当注解标注在属性的setter方法上,即默认取属性名作为bean名称寻找依赖对象。 推荐使用的方式 Resource(name=“personDaoBean”) private PersonDao personDao;/用于字段上注意:如果没有指定name属性,并且按照默认的名称仍然找不到依赖对象时, Resource注解会回退到按类型装配。但一旦指定了name属性,就只能按名称装配了。测试: 测试时使用下面的一个注解就可以了新建类PersonServiceBean3:package com.yinger.service.impl;import javax.annotation.Resource;import com.yinger.dao.PersonDao;import com.yinger.service.PersonService;public class PersonServiceBean3 implements PersonService /Resource默认是按照名称来装配,这里是放在字段上 Resource private PersonDao pDao;/这样设计就实现了业务层和数据层的彻底解耦 /默认的构造器 public PersonServiceBean3() System.out.println(instance me); /带参数的构造器 public PersonServiceBean3(PersonDao pDao) this.pDao=pDao; /save方法 public void save() pDao.save(); /初始化方法,这个方法是类被实例化了之后就会执行的! public void init() System.out.println(init); /销毁方法 public void destroy() System.out.println(destroy); public PersonDao getpDao() return pDao; Resource /放在属性的setter上 public void setpDao(PersonDao pDao) this.pDao = pDao; beans.xml中的配置: 测试结果:log4j:WARN No appenders could be found for logg
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 化粪池尾水处理施工方案
- 行业财务分析报告框架指南
- 网诊咨询创业方案设计
- 道路线路设计方案咨询
- 老年人产品咨询方案范文
- 地产开发营销方案
- 宁海五星级酒店施工方案
- 建筑淡彩配色方案设计图
- 隐藏式消防水池施工方案
- 学校心理咨询室宣传方案
- 正大杯全国大学生市场调查与分析大赛(试题340道含答案)
- 大学物业管理知识培训课程课件
- 假体周围骨折课件
- 建筑工程施工安全与技术管理相关知识试卷
- 2025年高等教育工学类自考-02382管理信息系统历年参考题库含答案解析(5套典型题)
- 2025年人教版新教材数学三年级上册教学计划(含进度表)
- 医院移动护理系统
- 初中道德与法治名师讲座
- 急性胆源性胰腺炎护理查房
- 《血管内导管相关性血流感染预防与诊治指南(2025)》解读 4
- 法布里病护理查房
评论
0/150
提交评论