上篇博文容器初始化时,使用new的方式来实力化对象,这篇博文我们利用配置文件+反射实力化对象,进一步封
装降低容器和组件的耦合度。下面我们先看一下配置文件。
[html]
- <?xml version="1.0" encoding="UTF-8"?>
- <beans>
- <bean id="dao" class="com.tgb.container.dao.impl.Dao4MySqlImpl" />
- <bean id="service" class="com.tgb.container.service.impl.ServiceImpl" />
- </beans>
看到上面的配置文件,除了命名空间没有,和Spring的配置文件已经很像了,下面我们就使用dom4j或jdom来读取
配置文件,并将配置文件中配置类利用反射实例化。本实例我们使用的jdom,大家也可以使用dom4j试一下。下面我
们看一下读取配置文件的代码:
[java]
- public interface BeanFactory {
- Object getBean(String id);
- }
[java]
- import java.util.HashMap;
- import java.util.List;
- import java.util.Map;
- import org.jdom.Document;
- import org.jdom.Element;
- import org.jdom.input.SAXBuilder;
- import org.jdom.xpath.XPath;
- import com.tgb.container.dao.Dao;
- import com.tgb.container.service.Service;
- /**
- * 从类路径加载配置文件
- *
- * liang
- *
- */
- public class ClassPathXmlApplicationContext implements BeanFactory {
- // 用于存放Bean
- private Map<String, Object> beans = new HashMap<String, Object>();
- public ClassPathXmlApplicationContext(String fileName) {
- this.readXML(fileName);
- }
- // 解析xml文件,通过反射将配置的beasn放到container中,并实现依赖注入
- private void readXML(String fileName) {
- // 创建SAXBuilder对象
- SAXBuilder saxBuilder = new SAXBuilder();
- // 读取资源,获得document对象
- Document doc;
- try {
- doc = saxBuilder.build(this.getClass().getClassLoader().getResourceAsStream(fileName));
- // 获取根元素
- Element rootEle = doc.getRootElement();
- // 从根元素获得所有的子元素,建立元素集合
- List listBean = XPath.selectNodes(rootEle, "/beans/bean");
- // 遍历根元素的子元素集合,扫描配置文件中的bean
- for (int i = 0; i < listBean.size(); i++) {
- Element bean = (Element) listBean.get(i);
- // 获取id属性值
- String id = bean.getAttributeValue("id");
- // 获取class属性值
- String clazz = bean.getAttributeValue("class");
- // 反射,实例化
- Object o = Class.forName(clazz).newInstance();
- beans.put(id, o);
- }
- // 依赖管理,这里还不灵活,但是原理是一样的
- Service service = (Service) beans.get("service");
- Dao dao = (Dao) beans.get("dao");
- // 依赖注入,Service实现依赖dao的实现
- service.setDao(dao);
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- /**
- * 查找组件
- *
- * id
- *
- */
- public Object getBean(String id) {
- return beans.get(id);
- }
- }
底,下面我们将bean的实例化以及依赖注入进行进一步的封装。
封装bean的实例化
为了做进一步的封装,我们将配置文件的属性封装成一个javabean,为了存放我们的属性值。如下所示:
[java]
- public class BeanDefinition {
- private String id;
- private String className;
- public BeanDefinition(String id, String className) {
- this.id = id;
- this.className = className;
- }
- public String getId() {
- return id;
- }
- public void setId(String id) {
- this.id = id;
- }
- public String getClassName() {
- return className;
- }
- public void setClassName(String className) {
- this.className = className;
- }
- }
[java]
- import java.util.ArrayList;
- import java.util.HashMap;
- import java.util.List;
- import java.util.Map;
- import org.jdom.Document;
- import org.jdom.Element;
- import org.jdom.input.SAXBuilder;
- import org.jdom.xpath.XPath;
- import com.tgb.container.dao.Dao;
- import com.tgb.container.service.Service;
- /**
- * 容器
- *
- * liang
- *
- */
- public class ClassPathXmlApplicationContext implements BeanFactory {
- // 用于存放Bean
- private List<BeanDefinition> beanDefines = new ArrayList<BeanDefinition>();
- // 用于存放Bean的实例
- private Map<String, Object> sigletons =new HashMap<String, Object>();
- public ClassPathXmlApplicationContext(String fileName) {
- this.readXML(fileName);
- this.instanceBeans();
- this.injectObject();
- }
- /**
- * 依赖注入,为bean对象的属性注入值
- * 这里还不灵活,但是原理是一样的
- */
- private void injectObject() {
- Service service = (Service) this.sigletons.get("service");
- Dao dao = (Dao) this.sigletons.get("dao");
- //依赖注入,Service实现依赖dao的实现
- service.setDao(dao);
- }
- /**
- * 完成bean的实例化
- */
- private void instanceBeans() {
- for(BeanDefinition beanDefinition : beanDefines){
- try {
- if(beanDefinition.getClassName() != null && !"".equals(beanDefinition.getClassName().trim())){
- sigletons.put(beanDefinition.getId(),Class.forName(beanDefinition.getClassName()).newInstance() );
- }
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- }
- /**
- * 读取xml配置文件
- */
- private void readXML(String fileName) {
- // 创建SAXBuilder对象
- SAXBuilder saxBuilder = new SAXBuilder();
- try {
- // 读取资源,获得document对象
- Document doc = saxBuilder.build(this.getClass().getClassLoader()
- .getResourceAsStream(fileName));
- // 获取根元素
- Element rootEle = doc.getRootElement();
- // 从根元素获得所有的子元素,建立元素集合
- List listBean = XPath.selectNodes(rootEle, "/beans/bean");
- // 遍历根元素的子元素集合,扫描配置文件中的bean
- for (int i = 0; i < listBean.size(); i++) {
- Element bean = (Element) listBean.get(i);
- // 获取id属性值
- String id = bean.getAttributeValue("id");
- // 获取class属性值
- String clazz = bean.getAttributeValue("class");
- BeanDefinition beanDefine = new BeanDefinition(id,clazz);
- // 将javabean添加到集合中
- beanDefines.add(beanDefine);
- }
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- /**
- * 获取bean实例
- */
- @Override
- public Object getBean(String beanName) {
- return this.sigletons.get(beanName);
- }
- }
我们知道容器不仅负责创建对象,而且可以管理对象的依赖关系,管理对象的生命周期等等。我们仅实现了容器
灵活创建对象的部分,依赖注入部分是由我们手动注入的。 对象的依赖关系还不灵活,但是我们已经能够看到IoC的
影子了,只是形似,还没有达到神似的目标。