三大框架SSH成长路程(十九)

17 篇文章 0 订阅
12 篇文章 0 订阅

一步步重构容器实现Spring框架——配置文件+反射实现IoC容器(十)

简单配置,反射

   上篇博文容器初始化时,使用new的方式来实力化对象,这篇博文我们利用配置文件+反射实力化对象,进一步封

装降低容器和组件的耦合度。下面我们先看一下配置文件。

<?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试一下。下面我
们看一下读取配置文件的代码:

public interface BeanFactory {  

    Object getBean(String id);  
}  
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;  

/** 
 * 从类路径加载配置文件 
 *  
 * @author 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();  
        }  
    }  

    /** 
     * 查找组件 
     *  
     * @param id 
     * @return 
     */  
    @Override  
    public Object getBean(String id) {  
        return beans.get(id);  
    }  
}  

看到上面的代码,我们发现读取配置文件的方法中包含了反射,代码的可读性太差,并且对面向对象的封装不够彻
底,下面我们将bean的实例化以及依赖注入进行进一步的封装。

封装bean的实例化

   为了做进一步的封装,我们将配置文件的属性封装成一个javabean,为了存放我们的属性值。如下所示:
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;  
    }  

}  

现在我们就可以把bean的实例化做进一步的封装了。

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;  

/** 
 * 容器 
 *  
 * @author 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的
影子了,只是形似,还没有达到神似的目标。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值