




已阅读5页,还剩4页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
对IOC和DI的理解首先说一下什么是IOC和DI,IOC是InversionofControl(控制反转)的简写,DI是DependencyInjection(依赖注入)的简写,martinfowler对IOC的解释为:“Inversionofcontrolisacommoncharacteristicofframeworks,sosayingthattheselightweightcontainersarespecialbecausetheyuseinversionofcontrolislikesayingmycarisspecialbecauseithaswheels.” 我想对这一概念进行一个个人的阐述,以方便我的理解。控制反转,从字面意思来看,就是控制权由被动变主动又变为被动,或被动变主动又变为被动。从这个角度来说,IOC就变得非常容易理解了。 举个例子:你的主管要求你做一件事情,这个时候就存在这么几个过程, 1、主管命令你做事情(这个时候主动权在主管,你是被动的) 2、你接到命令做事情(这个时候主题是你,你是主动的,控制权在你手里) 3、你完成事情(这个时候主题依然是你,控制权在你手里) 4、报告主管做完事情(主动权又叫交到主管手里了) 上面的整个过程就完成了一次IOC,从上面可以看出,IOC的基本思想是控制权的转换过程。 举个代码的例子: 假如有ClassA,ClassB,在A内部会初始化一个B,调用B的一个方法DoMethod publicClassB publicvoidDoMethod() /dosomthing; publicClassA publicvoidExcute() Bb=newB(); b.DoMethod(); 假如在Main函数中如下执行: Aa=newA(); a.Excute(); 从这两行代码来看,事实上也存在一个IOC的过程,aba,理解的关键点就在A的内部调用Excute的时候,方法b.DoMethod的执行。 理解了IOC,我们再看一下DI,从上面A调用B我们可以看出,在初始化一个A的实例时,也必须实例化一个B,也就是说如果没有B或者B出了问题,A就无法实例化,这就产生了一种依赖,就是A依赖B,这种依赖从设计的角度来说就是耦合,显然它是无法满足高内聚低耦合的要求的。这个时候就需要解耦,当然解耦有很多种方法,而DI就是其中一种。不管任何一种解耦方法,都不是说使A和B完全没有关系,而是把这种关系的实现变得隐晦,不那么直接,但是又很容易实现,而且易于扩展,不像上面的代码那样,直接new一个B出来。那就是为什么我们总是把IOC和DI联系到一起,是因为DI的基本思想就是IOC,而体现IOC思想的方法还有另外一个,那就是ServiceLocator,这个方法好像涉及到的很少。 DI,依赖注入,从字面意思就可以看出,依赖是通过外接注入的方式来实现的。这就实现了解耦,而DI的方式通常有三种: 构造器注入 属性设置器注入 接口注入(我感觉接口注入是同时存在于上两种注入方式的,而不应该独立出来) 以上的阐述只是为了先让我们能对IOC和DI有一个感性的理解,那么IOC它真正解决的问题是什么呢?我们讲了那么多主动、被动的问题,那我们是从什么视角来看待这个问题的呢?为什么你是主动,而我不是主动呢?这就需要一个参照物,这个参照物是什么呢?就是容器,在容器中来体现主动和被动。“用通俗话讲,就是由容器控制程序之间的关系,而非传统实现中,由程序代码直接操控。这也就是所谓”控制反转“的概念所在:控制权由应用代码中转到了外部容器,控制权的转移,是所谓反转,这是通常对IOC的一个解释。从容器的角度来看主动和被动,和由容器来控制程序之间的关系,应该是相通的,是一个意思。到这里我们就应该基本明白了,IOC要解决的就是程序之间调用的一个问题,它应该是一个逻辑层面的东西,是一个指挥中心,就像一支乐队的指挥,而程序就是乐器,通过指挥来协调各种乐器,来演奏出美好的音乐来Resource的概念Resource在Sping框架中起着不可或缺的作用,Sping框架使用Resource装载各种资源,这些资源包括配置文件资源、国际化属性文件资源等。下面我们来了解一下Resource的具体实现类。 ByteArrayResource:二进制数组表示的资源,二进制数组源可以在内存中通过程序构造。 ClassPathResource:类路径下的资源,资源以相对于类路径的方式表示,如:new ClassPathResource(com/baobaotao/beanfactory/bean.xml)。 FileSystemResource:文件系统资源,资源以文件系统路径的方式表示,如:new FileSystemResource(c:beans.xml)。 InputSteamResource:以输入流返回表示的资源。 ServletContextResource:为访问Web容器上下文中的资源而设计的类,负责从Web应用根目录中加载资源,它支持以流和Url的方式访问,在WAR解包的情况下,也可以通过File的方式访问,该类还可以直接从JAR包中访问资源。 UrlResource:Url封装了.URL,它使用户能够访问任何可以通过URL表示的资源,如文件系统的资源、HTTP资源、FTP资源等。 有了这个抽象的资源类后,我们就可以将Spring的配置信息放置在任何地方(如数据库、LDAP中),只要最终可以通过Resource接口返回配置信息就可以了。Java标准的 .URL接口和多种URL前缀处理类并不能很好地满足所有底层资源访问的需要。比如,还没有能从类路径或者ServletContext 的相对路径获得资源的标准URL实现。虽然能为特定的URL前缀注册新的处理类(类似已有前缀 http: 的处理类),但是这样做通常比较复杂,而且URL接口还缺少一些有用的功能,比如检查指向的资源是否存在的方法。4.2. Resource 接口Spring的 Resource 接口是为了提供更强的访问底层资源能力的抽象。 public interface Resource extends InputStreamSource boolean exists(); boolean isOpen(); URL getURL() throws IOException; File getFile() throws IOException; Resource createRelative(String relativePath) throws IOException; String getFilename(); String getDescription();public interface InputStreamSource InputStream getInputStream() throws IOException;Resource 接口一些比较重要的方法如下: getInputStream(): 定位并打开资源,返回读取此资源的一个 InputStream。每次调用预期会返回一个新的 InputStream,由调用者负责关闭这个流。exists(): 返回标识这个资源在物理上是否的确存在的 boolean 值。isOpen(): 返回标识这个资源是否有已打开流的处理类的 boolean 值。如果为 true,则此InputStream 就不能被多次读取,而且只能被读取一次然后关闭以避免资源泄漏。除了 InputStreamResource,常见的resource实现都会返回 false。 getDescription(): 返回资源的描述,一般在与此资源相关的错误输出时使用。此描述通常是完整的文件名或实际的URL地址。 其它方法让你获得表示该资源的实际的 URL 或 File 对象(如果隐含的实现支持该方法并保持一致的话)。 Spring自身处理资源请求的多种方法声明中将Resource 抽象作为参数而广泛地使用。 Spring APIs中的一些其它方法(比如许多ApplicationContext的实现构造函数),使用普通格式的 String 来创建与context相符的Resource,也可以使用特殊的路径String前缀来让调用者指定创建和使用特定的 Resource 实现。 Resource不仅被Spring自身大量地使用,它也非常适合在你自己的代码中独立作为辅助类使用。用户代码甚至可以在不用关心Spring其它部分的情况下访问资源。这样的确会造成代码与Spring之间的耦合,但也仅仅是与很少量的辅助类耦合。这些类可以作为比 URL 更有效的替代,而且与为这个目的而使用其它类库基本相似。 需要注意的是 Resource 抽象并没有改变功能:它尽量使用封装。 比如 UrlResource 封装了URL,然后使用被封装的 URL 来工作。 4.3. 内置 Resource 实现Spring提供了很多 Resource 的实现: 4.3.1. UrlResource UrlResource 封装了.URL,它能够被用来访问任何通过URL可以获得的对象,例如:文件、HTTP对象、FTP对象等。所有的URL都有个标准的 String表示,这些标准前缀可以标识不同的URL类型,包括file:访问文件系统路径,http: 通过HTTP协议访问的资源,ftp: 通过FTP访问的资源等等。 UrlResource 对象可以在Java代码中显式地使用 UrlResource 构造函数来创建。但更多的是通过调用带表示路径的 String 参数的API函数隐式地创建。在后一种情况下,JavaBeans的 PropertyEditor 会最终决定哪种类型的 Resource 被创建。如果这个字符串包含一些众所周知的前缀,比如 classpath:,它就会创建一个对应的已串行化的 Resource。 然而,如果不能分辨出这个前缀,就会假定它是个标准的URL字符串,然后创建UrlResource。 4.3.2. ClassPathResource 这个类标识从classpath获得的资源。它会使用线程context的类加载器(class loader)、给定的类加载器或者用来载入资源的给定类。如果类路径上的资源存在于文件系统里,这个 Resource 的实现会提供类似于java.io.File的功能。而如果资源是存在于还未解开(被servlet引擎或其它的环境解开)的jar包中,这些 Resource 实现会提供类似于.URL 的功能。 ClassPathResource对象可以在Java代码中显式地使用ClassPathResource 构造函数来创建。但更多的是通过调用带表示路径的String参数的API函数隐式地创建。在后一种情况下,JavaBeans的 PropertyEditor 会分辨字符串中 classpath: 前缀,然后相应创建 ClassPathResource。 4.3.3. FileSystemResource 这是为处理 java.io.File 而准备的Resource实现。它既可以作为File提供,也可以作为URL。 4.3.4. ServletContextResource 这是为 ServletContext 资源提供的 Resource 实现,它负责解析相关web应用根目录中的相对路径。 它始终支持以流和URL的方式访问。 但是只有当web应用包被解开并且资源在文件系统的物理路径上时,才允许以 java.io.File 方式访问。是否解开并且在文件系统中访问,还是直接从JAR包访问或以其它方式访问如DB(这是可以想象的),仅取决于Servlet容器。 4.3.5. InputStreamResource 这是为给定的 InputStream 而准备的 Resource 实现。它只有在没有其它合适的 Resource 实现时才使用。而且,只要有可能就尽量使用 ByteArrayResource 或者其它基于文件的Resource 实现。 与其它 Resource 实现不同的是,这是个 已经 打开资源的描述符-因此 isOpen() 函数返回 true。 如果你需要在其它位置保持这个资源的描述符或者多次读取一个流,请不要使用它。 4.3.6. ByteArrayResource 这是为给定的byte数组准备的 Resource 实现。 它会为给定的byte数组构造一个 ByteArrayInputStream。 它在从任何给定的byte数组读取内容时很有用,因为不用转换成单一作用的 InputStreamResource。 4.4. ResourceLoader ResourceLoader 接口由能返回(或者载入)Resource 实例的对象来实现。 public interface ResourceLoader Resource getResource(String location);所有的application context都实现了 ResourceLoader 接口, 因此它们可以用来获取Resource 实例。 当你调用特定application context的 getResource() 方法, 而且资源路径并没有特定的前缀时,你将获得与该application context相应的 Resource 类型。例如:假定下面的代码片断是基于ClassPathXmlApplicationContext 实例上执行的: Resource template = ctx.getResource(some/resource/path/myTemplate.txt);这将返回ClassPathResource;如果是基于FileSystemXmlApplicationContext 实例上执行的,那你将获得FileSystemResource。而对于 WebApplicationContext 你将获得ServletContextResource,依此类推。 这样你可以在特定的application context中用流行的方法载入资源。 另一方面,无论什么类型的application context, 你可以通过使用特定的前缀 classpath: 强制使用ClassPathResource。 Resource template = ctx.getResource(classpath:some/resource/path/myTemplate.txt);同样的,你可以用任何标准的 .URL 前缀,强制使用 UrlResource : Resource template = ctx.getResource(file:/some/resource/path/myTemplate.txt);Resource template = ctx.getResource(/resource/path/myTemplate.txt);下面的表格概述了 String 到 Resource 的转换规则: Table 4.1. Resource strings前缀 例子 说明 classpath: classpath:com/myapp/config.xml 从classpath中加载。 file: file:/data/config.xml 作为 URL 从文件系统中加载。 http: http:/myserver/logo.png 作为 URL 加载。 (none) /data/config.xml 根据 ApplicationContext 进行判断。 a 参考标题为 Section 4.7.3, “ FileSystemResource 提示” 的章节。 4.5. ResourceLoaderAware 接口ResourceLoaderAware是特殊的标记接口,它希望拥有一个ResourceLoader 引用的对象。 public interface ResourceLoaderAware void setResourceLoader(ResourceLoader resourceLoader);当实现了 ResourceLoaderAware接口的类部署到application context(比如受Spring管理的bean)中时,它会被application context识别为 ResourceLoaderAware。接着application context会调用setResourceLoader(ResourceLoader)方法,并把自身作为参数传入该方法(记住,所有Spring里的application context都实现了ResourceLoader接口)。 既然 ApplicationContext 就是ResourceLoader,那么该bean就可以实现 ApplicationContextAware接口并直接使用所提供的applicatio
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2025-2030中国区块链供应链金融风险控制与中小企业融资报告
- 2025-2030中国公寓行业数字化转型路径与技术应用报告
- 地理必修一湘教版 第三节 大气环境常见的天气系统-锋面教学设计
- 6 闻一闻 尝一尝教学设计-2025-2026学年小学科学一年级上册青岛版(五四制2024)
- 护理专业笔试常考题库及答案解析
- 安全生产法宣贯试题库及答案解析
- 零陵路安全性测试题及答案解析
- 最牛基金从业考试及答案解析
- 梦幻仙境:世界的奇幻之旅
- 洗衣机使用手册
- 降低口腔炎发生率的品管圈实践
- 职称评聘工作管理制度
- 三腔空肠营养管构造及护理
- 2025年人教PEP版(2024)小学英语四年级上册(全册)教学设计(附目录)
- DB31/T 1367-2022养老机构服务质量监测与评价规范
- 电费代付款协议书
- 2025年(第一季度)电网工程设备材料信息参考价(加密)
- 贵金属废料提炼合同协议
- 中国传统木工工艺课件
- 有限空间作业培训内容
- 淋巴瘤PET-CT及PET-MR显像临床应用指南(2025版)解读课件
评论
0/150
提交评论