假设项目层次划分包括logic层和dao层,logic层调用dao层完成业务逻辑,dao层一般与数据库交互。定义两个组件,TestLogic和TestDao,分别操作接口ILogic和IDao,这样程序开发时需要考虑怎样管理这两个组件。
这种方式中,当TestLogic组件需要调用TestDao组件时,直接使用关键字new
IDao testDao = new TestDao();
这种方式简单直观,但造成了对外部组件的严重依赖,程序高度耦合,效率低下。当项目需要更换组件时需要修改大量代码,不利于项目的维护和扩展。
工厂模式指的是定义一个工厂,这个工厂用来产生组件,这样其它组件需要该组件时直接通过工厂来获取。例如定义产生TestDao组件的工厂
public class TestDaoFactory { public IDao createTestDao() { return new TestDao(); } }
这样TestLogic组件需要调用TestDao组件时使用如下方式
IDao testDao = TestDaoFactory.createTestDao();
这种方式下TestLogic组件无需与TestDao组件以硬编码方式耦合在一起,只需要与产生TestDao组件的工厂TestDaoFactory耦合。当更换组件时只需要修改工厂类。
使用工厂模式可以实现一定程度上的解耦,但不同的组件之间会有着不同的依赖关系,这样工厂的实现和管理又成了新的问题。IoC容器就在这样的需求下产生了。
这种方式下,使用配置文件将组件的依赖和管理与业务代码分离,创建被调用组件(TestDao)的工作不再由调用者(TestLogic)来完成,而是由IoC容器来完成,因此称为控制反转。组件是由IoC容器创建了,但是怎么将TestDao组件交给TestLogic组件使用,也就是TestLogic组件如何取得TestDao组件,使用注入方式交给TestLogic组件使用,因此也称为DI(依赖注入)。而注入的方式有接口注入,构造注入和set方法注入,Spring支持后两种方式。
介绍SpringIoC的使用方法,项目地址:https://github.com/ichunming/SpringIoC。该工程为Maven工程,不需要下载spring相关jar包。项目包含了两个组件TestLogic,TestDao及相应的接口,TestLogic组件调用TestDao组件。这里使用set方法注入dao层组件,即TestLogic中定义dao属性,并创建该属性对应的set方法。这样进入spring核心部分--applicationContext.xml配置文件,配置文件中主要就是Bean的配置:
--------------------------------------------------------------------------
-- 注册TestDao组件 -- <bean id="testDao" class="com.ioc.dao.TestDao"></bean> -- 注册TestLogic组件 -- <bean id="testLogic" class="com.ioc.logic.TestLogic"> -- 依赖注入testDao -- <property name="dao" ref="testDao"></property> </bean>
--------------------------------------------------------------------------
可以看到注册TestLogic组件时配置了相应的property,意思是创建testLogic组件时调用setDao方法,参数是testDao,这样testDao组件就注入到testLogic中了。
最后测试一下是否能从spring容器中取得组件
--------------------------------------------------------------------------
// 加载spring容器 ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); // 从容器中取得testLogic组件 ILogic logic = (TestLogic)context.getBean("testLogic"); // 使用该组件 logic.print();
--------------------------------------------------------------------------
总体来说,可以将Spring看成一个大的工厂,用来生产和管理所有组件。对于项目的维护和扩展,当需要更换组件是只要修改配置文件(或者再修改少量代码)就可以实现。
这里简单模拟IoC容器的实现,主要使用jdom读取XML,将所有的Bean保存在Map中,如果需要注入就是用set方法注入。
新建MyClassPathXmlApplicationContext类,里面有map属性,用来保存所有的Bean。构造函数中加载并读取XML文件,遍历所有的bean元素,生成相应的组件并写入map中。提供getBean方法,用于取得组件。具体实现与上面IoC基本使用放在一起,git地址:https://github.com/ichunming/SpringIoC。
原文:http://www.cnblogs.com/zhangchunming/p/5176415.html