ImageVerifierCode 换一换
格式:DOCX , 页数:65 ,大小:252.77KB ,
资源ID:8381321      下载积分:12 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.bdocx.com/down/8381321.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(疯狂java实例第14章 自己开发IoC容器.docx)为本站会员(b****5)主动上传,冰豆网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰豆网(发送邮件至service@bdocx.com或直接QQ联系客服),我们立即给予删除!

疯狂java实例第14章 自己开发IoC容器.docx

1、疯狂java实例第14章 自己开发IoC容器第14章 自己开发IoC容器14.1 IoC简介在平时的开发中,当我们正在编写的某一个类需要用到另外的一个类(组件)的时候,我们都需要通过new的关键来创建该类的实例,那么有没有更好的方式,可以不在我们的代码中直接去new这个类,就可以得到该实例呢?IoC的概念很好的帮助我们解决了这个问题,当我们需要在一个类中使用另外的类时,可以通过一些配置来得到该类的实现。IoC是Inversion of Control简称,又称控制反转,一个类需要另外一个类的实例,可以通过某个容器获得,而不在类的内部创建,得到什么样的实例,由容器去决定,而不是由该类决定。搞清楚

2、了控制反转的概念后,我们再来了解什么叫依赖注入。依赖注入(Dependency Injection)与控制反转是同一个概念,我们创建某个类的实例由IoC容器完成,如果该类需要使用另外的类实例,那么可以在IoC容器中向该类注入需要被调用的实例。无论是控制反转还是依赖注入,采用这种方式来创建类的实例,可以使得我们的代码更加清晰明了,将各个类之间的依赖关系反映到IoC容器中,可以更动态、灵活和透明的管理各个对象。在J2EE领域中使用IoC的概念,可以将各个功能不同的组件统一放到IoC容器中,程序员只需要关注各个组件的实现,而不需要关注各个组件的依赖的关系。常用的IoC容器有Spring的IoC容器、

3、webwork的IoC容器、google-guice,apache的HiveMind等。笔者面试过一些工作了几年的程序员,这些程序员很多都说自己精通Spring,精通IoC容器,但是如果一问IoC容器是如何帮我们创建类实例的,很多都不知道如何回答。在下面章节中,我们将通过编写一个简单的IoC容器,来说明IoC容器是如何帮我们创建类的实例、如何实现依赖注入,最后并通过一个整合的例子,来说明IoC容器给我们带来什么样的好处。14.2 使用技术简介在本章开发IoC容器时,所涉及的技术有如下几种: Java的反射机制 dom4j Junit14.2.1 Java反射简介在Java运行时环境中,如果我们

4、需要得到某一个类的具体信息,那么就可以使用Java的反射机制,该机制可以让我们动态的得到某个类型的属性、构造器和方法。Java的反射机制可以在运行时构造某一个类的实例,在运行时调用任意一个对象的方法。在本章中,我们需要在运行时去动态的加载配置文件,再根据这些配置文件去创建某一个类的实现,并为这些实例设置相应的属性,因此我们需要使用Java的反射机制。14.2.2 dom4jdom4j是一个常用的XML解析项目,该项目是一个易用的开源项目,它应用于Java平台,支持使用Dom、SAX来解析XML文件。Dom4j的使用非常简单,只需要使用该项目所提供的解析类,就可以轻松的读取到相应的XML文件,并

5、可以得到这些xml的相关内容。本章中我们采用了XML文件作为我们的IoC容器的配置文件,因此使用dom4j就非常的合适。14.2.3 JunitJunit是一个单元测试框架,供Java程序员编写单元测试。在本章中,我们每编写一个功能点,就需要对该功能进行单元测试,一来可以展示我们所编写程序的效果,二来可以保证我们的程序的质量。如果站在XP(极限编程)的角度来讲,编写测试可以让我们的代码更加健壮,更不惧任何的变更,对我们项目的发展有长远的利益。本章的重点是IoC容器,使用这个测试框架,目的是展示我们代码的效果,我们当前所使用的是Junit4。14.3 确定配置文件内容、编写DTD在编写IoC容器

6、之前,我们需要编写XML文件,这些XML文件用来定义人们IoC容器的一些配置,例如声明我们需要创建哪些对象(bean),为这些对象(bean)提供名字和类名,让我们的IoC容器根据这些信息去创建相应的bean。除了定义bean的名字和类名外,还需要定义一些其他的属性,例如该bean是否为单态,是否需要延迟加载定。确定了配置文件的内容后,我们开始着手编写DTD文件。14.3.1 声明bean在整个IoC容器中,每一个bean代表具体的某个类,因此我们的根节点为beans,beans下有多个bean,可以让我们配置具体的某个类。XML文件的具体配置如下: 定义好了bean节点好,我们需要为bean

7、节点指定一个名字和类名,表示这个bean所对应的名称与类型,这些我们的IoC容器得到这些配置后,就可以帮我们创建这些类的实例。具体的配置如下: 以上的bean配置表示我们在IoC容器中创建了一个myDate的bean,该bean的类型是java.util.Date。14.3.2 声明单态的bean定义一个bean除了需要显式声明该bean的名称和类型外,还需要告诉我们的IoC容器,该bean是否为单态,如果该bean是单态的话,那么IoC容器在启动的时候,就只会为该bean创建一个实例,并将该实例缓存起来,如果该bean配置成非单态的话,那么就不进行缓存,每次请求这个bean的时候,就重新创建

8、一个。我们为bean的配置添加一个singleton属性,用来声明bean是否为单态。 以上配置的黑体部分,我们配置了myDate这个bean为非单态,在一般的情况下,我们可以不指定singleton属性,让singleton属性在不显式声明的情况下的值为true,给配置节点提供默认值,在14.4准备DTD文件中有详细说明。14.3.3 声明延迟加载当IoC容器启动的时候,容器是否需要马上创建这个bean,我们可以为配置文件提供一个属性,让容器知道我们在容器初始化的时候,是否需要创建。我们为bean提供一个lazy-init的属性:以上的配置代码中,声明了myDate需要延迟加载,为bean节

9、点加了这个属性后,beans节点也可以提供一个default-lazy-init的属性,表示这份配置文件下的所有bean,如果lazy-init属性的值为default的时候,就使用beans节点(根节点)的default-lazy-init所配置的值: 以上的配置,如果myDate的bean声明为default的话,那么就按照beans的default-lazy-init属性来决定是否需要延迟加载。如果对bean的lazy-init属性不指定值的话,那么就为这个lazy-init属性指定为default,表示这个bean是否延迟加载取决于beans的配置,而beans的default-laz

10、y-init属性不显式指定的话,可以使用false作为默认值。14.3.4 声明设值注入到bean的属性IoC容器除了可以帮我们创建bean之外,还可以帮助我们将对应的属性设置到该bean的实例里面,我们需要为每个bean注入一些属性,让该bean的实例得到这些属性,这些属性有可能是一些普通的值,也有可能是另外的定义的bean。在这里我们使用设值注入,设值注入,就是创建了bean的实例后,再获得该bean配置的一些属性,通过该bean里面的setter方法,设值到该bean的实例中。 以上的配置中的黑体部分,我们为student的bean注入了一个school的bean,这样,school和s

11、tudent这两个bean就产生了依赖关系,这样的注入我们就叫依赖注入,以上的注入方式是依赖注入中的设值注入。那么我们的配置文件中需要为bean加入一个property的子节点,该节点里面有一个name属性,property节点下面有一个ref子节点,ref子节点指向某一个容器中的bean。除了注入另外定义的bean外,还可以向bean中注入一些普通的属性: 18 以上的配置表示向student这个bean中注入了一个Integer的值,对应Student的age属性。因此,property节点下面可以出现ref节点和value节点,但是,每一个property只能出现一次ref节点或者val

12、ue节点,因为我们一个property只会设置一个属性。14.3.5 声明构造注入到bean的属性14.3.4小节中,我们定义配置文件中为bean提供property节点进行设值注入,本小节我们定义构造注入的节点。构造注入,也就是通过bean中定义的构造参数,在创建这个bean的实例时,就将这些参数通过调用该bean的构造器,将这些配置的属性传递给该bean。 以上配置的黑体部分,声明了创建student这个bean的时候,我们需要为Student类提供一个构造器,构造器的参数为School类型,那么IoC容器在创建时,就会根据constructor-arg声明的属性,去调用Student的构

13、造器。与14.3.4中的设值注入一样,除了可以提供ref元素外,还可以提供value元素,构造注入一些另外的普通属性。 20 这样的配置,我们就可以为Student进行构造注入,并在创建bean的实例时,提供一个Integer类型的构造参数。14.3.6 自动装配自动装配,就是不需要指定bean的属性,从IoC容器中查找bean所需要的属性,将这些查找到的bean以设值注入的方式依赖注入到目标的bean中。 以上的student提供了autowire属性,该属性值为byName,表示根据bean的名称自动注入到student中,如果Student类中有一个setSchool的setter方法,

14、并且参数为Schoold对象,那么容器就需要自动的将School的bean通过设值注入设置到Student中。与延迟加载一样,也可以为beans节点提供一个default-autowire属性,声明该beans根节点下面所有的bean节点,如果autowire的值为default,那么就可以进行自动装配。 在本例中autowire的值我们定义为只允许为no或者byName。如果autowire的值为no的话,表示不需要自动装配。bean的autowire属性默认值为default。确定了IoC的配置文件需要配置的内容,那么接下来,我们就可以根据上述的配置内容,编写相关的约束文件(DTD)。14

15、.3.7 准备DTD文件文档定义类型(DTD)可以定义合法的XML文档构建模块,对我们所编写的一些XML文件进行约束,也就是说,当一份XML指定了某份DTD文件时,那么该XML文件就必须遵守该DTD文件的约束。简单的说,DTD就是一种对XML文件定制的规范。当我们需要为一份XML定义某份DTD规范的时候,在XML文件头中声明:以上的XML文件头,声明了该份XML由http:/www.crazyit.org/beans.dtd这一份dtd来约束,每个元素都需要遵守该份DTD中所声明的文档结构。根据14.3.1到14.3.6里面定义的配置文件的内容,我们可以开始编写DTD文件。以下为我们的IoC容

16、器配置文件的DTD文件:通过以上的代码,那么该份DTD的各个节点可以概括为如下几个: beans节点:根节点为beans,beans的属性有default-lazy-init和autowire,这两个属性的默认值(不需要显式提供)为false和no。 bean节点:beans下面有多个bean节点,bean节点必须要显式提供id和class属性,可以不必显式提供lazy-init,singleton和autowire属性,lazy-init的默认值为default,表示该值由beans的default-lazy-init来决定,singleton的默认值为true,而且只允许有true和fal

17、se两个值,autowire属性的默认值是default,由beans的default-autowire来决定。 construct-arg节点:ref、value和null都可以作为该节点的子节点,该节点没有属性。 property节点:ref、value和null都可以作为该节点的子节点,property节点有一个name属性,而且是必须指定的。 ref节点:该节点没有子节点,只有一个必须指定的bean属性。 value节点:value节点只有一个type属性,用于指定该值的类型。编写完DTD文件后,那么我们可以在XML的文件头中声明DTD。以上的XML文件头,表示我们使用某份DTD文件作

18、为XML的约束,指定DTD文件路径时,我们暂时使用绝对路径,指向我们上面编写的那份DTD文件,在下面的章节中,将会讲解如何将绝对路径变成url。14.4 读取XML文件在14.2中,我们已经确定了使用dom4j来读取XML文件,我们需要明白,当在创建一个IoC容器的时候,我们就开始读取XML文件,当取完之后,可以将XML中我们所需要的信息缓存起来,也就是进行一次读取即可,如果进行多次读取,那么将会影响性能。在使用dom4j之前,我们需要下载dom4j的包,下载完包之后,可以将包放到项目的环境变量中。dom4j的包可以从sourceforge中下到,下载的地址为:14.4.1 加载XML文件在本

19、小节开头,我们已经确定了只读取一次XML,那么我们就新建一个类,用于读取XML,并将读取到的Document对象缓存。建立DocumentHolder接口。代码清单:codeIoCmainorgcrazyitiocxmlDocumentHolder.javapublic interface DocumentHolder /根据文件的路径返回文档对象 Document getDocument(String filePath);DocumentHolder接口只有一个方法,用于获得一个Document对象,参数是XML文件的路径。为该接口新建一个实现类XmlDocumentHolder。代码清单:

20、codeIoCmainorgcrazyitiocxmlXmlDocumentHolder.javapublic class XmlDocumentHolder implements DocumentHolder /新建一个Map对象, 用于保存读取到的多份XML文件 private Map docs = new HashMap(); public Document getDocument(String filePath) Document doc = this.docs.get(filePath); if (doc = null) this.docs.put(filePath, readDoc

21、ument(filePath); return this.docs.get(filePath); /根据文件路径读取Document private Document readDocument(String filePath) try /使用SAXReader来读取xml文件 SAXReader reader = new SAXReader(true); /使用自己的EntityResolver reader.setEntityResolver(new IoCEntityResolver(); File xmlFile = new File(filePath); /读取文件并返回Documen

22、t对象 Document doc = reader.read(xmlFile); return doc; catch (Exception e) e.printStackTrace(); throw new DocumentException(e.getMessage(); 以上代码中,我们使用了一个Map对象来保存多个Document对象,当外界使用getDocument方法的时候,直接从Map对象中获取该Document对象,如果取到就返回,如果取不到该对象,就通过私有方法readDocument来读取。注意以上代码的黑体部分,我们使用了自定义的EntityResolver对象,IoCEn

23、tityResolver的代码如下。代码清单:codeIoCmainorgcrazyitiocxmlIoCEntityResolver.javapublic class IoCEntityResolver implements EntityResolver public InputSource resolveEntity(String publicId, String systemId) throws SAXException, IOException /先从本地寻找dtd if (http:/www.crazyit.org/beans.dtd.equals(systemId) InputStream stream = IoCEntityResolver.class. getResourceAsStream(/org/crazyit/ioc/beans/beans.dtd); return new InputSo

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1