IoC容器总结与简单模拟
来源:互联网 发布:javascript的oop写法 编辑:程序博客网 时间:2024/06/05 00:50
IoC是一种通用的设计原则,而DI(Dependency Injection,依赖注入)则是具体的设计模式,它体现了IoC的设计原则。DI是IoC典型的实现,所以IoC与DI术语会被混用。IoC与DI的关系就好比Java中的"接口"和"接口的实现类"的关系一样。
在DI模式下,容器全权负责的组件的装配,容器以一些预先定义好的方式(例如setter方法或构造函数)将匹配的资源注入到每个组件里。目前有三种类型的DI:
- setter注入,setter注入会存在一些问题,1. 容易出现忘记调用setter方法注入组件所需要的依赖,将会导致NullPointerException异常。2. 代码会存在安全问题,第一次注入后,不能阻止再次调用setter,除非添加额外的处理工作。但是由于setter注入非常简单所以非常流行(绝大多数Java IDE都支持自动生成setter方法)。
- 构造器注入,构造器注入能够一定程度上解决setter注入的问题。但是该中注入方式也会带来一些问题,如果组件有很多的依赖,则构造函数的参数列表将变得冗长,会降低代码可读性。
- 接口注入 ,该注入方式使用的非常少,它要求组件必须实现某个接口,容器正是通过这个接口实现注入依赖的。接口注入的缺点比较明显,使用接口注入需要实现特定的接口,而接口又特定于容器,所以组件对容器产生了依赖,一旦脱离容器,组件不能重用。这是一种"侵入式"注入。
其中"setter注入"和"构造器注入"是被广泛运用的,绝大多数的IoC容器都支持这两种DI类型。
模仿Spring IoC容器
假设一个系统的功能之一是能够生成PDF或HTML格式的报表。
/*生成报表的通用接口*/public interface ReportBuilder{ public void build(String data);}
生成PDF和HTML格式的实现类:
/*生成HTML格式报表*/public class ReportHtmlBuilder implements ReportBuilder { @Override public void build(String data) { /*示意代码*/ System.out.println("build html report!"); }}/*生成PDF格式报表*/public class ReportPdfBuilder implements ReportBuilder { @Override public void build(String data) { System.out.println("build pdf report!"); }}
报表服务类:
/*报表服务类*/public class ReportService { /*依赖"ReportBuilder"*/ private ReportBuilder builder; public ReportBuilder getBuilder() { return builder; } /*setter注入*/ public void setBuilder(ReportBuilder builder) { this.builder = builder; } public void builderYearReport(int year) { this.builder.build("data"); }}
IoC容器配置文件"component.properties"
pdfBuilder=com.beliefbitrayal.ioc.inter.imp.ReportPdfBuilderhtmlBuilder=com.beliefbitrayal.ioc.inter.imp.ReportHtmlBuilderreportService=com.beliefbitrayal.ioc.server.ReportServicereportService.builder=htmlBuilder
IoC容器:
public class Container{ /*用于储存Component的容器*/ private Map<String, Object> repository = new HashMap<String, Object>(); public Container() { try { /*读取容器配置文件"component.properties"*/ Properties properties = new Properties(); properties.load(new FileInputStream("src/component.properties")); /*获取配置文件的每一行信息*/ for(Map.Entry<Object, Object> entry : properties.entrySet()) { String key = (String)entry.getKey(); String value = (String)entry.getValue(); /*处理配置文件的每一行信息*/ this.handler(key, value); } } catch (Exception e) { e.printStackTrace(); } } private void handler(String key,String value) throws Exception { /* * reportService=com.beliefbitrayal.ioc.server.ReportService * reportService.builder=htmlBuilder * 第一种情况,key值中间没有"."说明为一个新组件。对它的处理为创建它的对象,将其对象放入Map中。 * 第二种情况,key值中间出现"."说明这个属性条目是一个依赖注入。根据"."的位置将这个key值划分为两部分,第一部分为组件的名字,第二部分为 * 该组件需要设置的属性。 */ String[] parts = key.split("\\."); /*情况1*/ if(parts.length == 1) { /*通过反射的方式创建组件的对象*/ Object object = Class.forName(value).newInstance(); this.repository.put(key, object); } else { /*对于情况2,首先用key值的第一部分(组件名)获取组件*/ Object object = this.repository.get(parts[0]); /*再使用value值指定的组件名从Map对象中获取依赖*/ Object reference = this.repository.get(value); /*将获取的依赖注入到指定的组件的相应属性上,"PropertyUtils"类属于Apache下Commons BeanUtil第三方类库, * 要使用它还需要下载Commons Logging第三方类库 */ PropertyUtils.setProperty(object, parts[1], reference); } } public Object getComponent(String key) { return this.repository.get(key); }}
根据配置文件,我们在场景类中使用的报表应该是HTML格式的:
public class Client{ public static void main(String[] args) { /*创建容器*/ Container container = new Container(); /*从容器中获取"报表服务类"*/ ReportService reportService = (ReportService)container.getComponent("reportService"); /*显示报表*/ reportService.builderYearReport(0); }}
控制台的输出:
build html report!
我们若需要PDF格式的只需要修改属性文件即可:
pdfBuilder=com.beliefbitrayal.ioc.inter.imp.ReportPdfBuilderhtmlBuilder=com.beliefbitrayal.ioc.inter.imp.ReportHtmlBuilderreportService=com.beliefbitrayal.ioc.server.ReportServicereportService.builder=pdfBuilder
场景类不变,控制台输出:
build pdf report!
容器可以从基于文本的控制文件中读取组件的定义,这使得容器可以重用。现在即使随意改变组件的定义,都不用修改容器的代码。这个例子很好的演示了IoC容器的核心原理和机制。
通过以上分析和举例,控制反转IoC就是一个组件的依赖是由容器来装配,组件不做定位查询,只提供普通的Java方法让容器去装配依赖关系,IoC容器是一般通过setter注入或构造函数注入的方式将依赖注入到组件中的,组件的依赖我们一般通过一个配置文件来描述(XML或Properties),配置文件在IoC容器被构建时读取解析。
原文地址:http://www.cnblogs.com/beliefbetrayal/archive/2012/02/02/2335192.html
- IoC容器总结与简单模拟
- IoC容器总结与简单模拟
- 手动模拟IOC容器
- php 简单ioc容器
- 模拟spring中的IOC容器
- spring 简单模拟 ioc
- IOC容器,其实很简单
- spring ioc容器简单理解
- IOC容器的简单介绍
- Java反射机制模拟Spring IOC容器
- 简单模拟Spring IOC功能
- 简单模拟 Spring 的 ioc
- IOC容器原理与实现
- Unity IOC容器的简单应用
- spring IoC容器初始化简单分析
- Spring 容器IOC解析及简单实现
- Spring的Ioc容器简单实现
- 深入理解Spring IOC,实现简单IOC容器
- Ubuntu 11.10安装VMWare Tools小结
- 全面剖析《自己动手写操作系统》第五章---makefile文件
- iis8新特性
- git撤销commit
- Oracle ADF Hierarchy Viewer控件使用简介
- IoC容器总结与简单模拟
- 进程间通过共享内存通信
- Android Handler的使用(一)
- hdu1207汉诺塔II
- 在ubuntu 下查找某个系统命令的源代码
- first blog for C
- 栈
- Ubuntu忘记登陆密码怎么办?
- 关于学习的总结