【SSH进阶之路】一步步重构容器实现Spring框架——配置文件+反射实现IoC容器(十)

目录
     【SSH进阶之路】一步步重构容器实现Spring框架——从一个简单的容器开始(八)
     【SSH进阶之路】一步步重构容器实现Spring框架——解决容器对组件的“侵入式”管理的两种方案--主动查找和控制反转(九)
     【SSH进阶之路】一步步重构容器实现Spring框架——配置文件+反射实现IoC容器(十)
     【SSH进阶之路】一步步重构容器实现Spring框架——彻底封装,实现简单灵活的Spring框架(十一)已更新


       上上篇博文【SSH进阶之路】一步步重构容器实现Spring框架——从一个简单的容器开始(八),我们为了去掉接

口对具体实现的依赖关系,封装了一个特别简陋的容器。

       上篇博文【SSH进阶之路】一步步重构容器实现Spring框架——解决容器对组件的“侵入式”管理的两种方案--主

动查找和控制反转(九),我们利用控制反转,去掉了组件对容器的依赖。

  

简单配置,反射

  

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

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

[html]  view plain copy print ? 在CODE上查看代码片 派生到我的代码片
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <beans>  
  3.   
  4.   <bean id="dao" class="com.tgb.container.dao.impl.Dao4MySqlImpl" />  
  5.     
  6.   <bean id="service" class="com.tgb.container.service.impl.ServiceImpl" />  
  7.       
  8. </beans>  

      看到上面的配置文件,除了命名空间没有,和Spring的配置文件已经很像了,下面我们就使用dom4j或jdom来读取

配置文件,并将配置文件中配置类利用反射实例化。本实例我们使用的jdom,大家也可以使用dom4j试一下。下面我

们看一下读取配置文件的代码:

[java]  view plain copy print ?
  1. public interface BeanFactory {  
  2.   
  3.     Object getBean(String id);  
  4. }  
[java]  view plain copy print ?
  1. import java.util.HashMap;  
  2. import java.util.List;  
  3. import java.util.Map;  
  4.   
  5. import org.jdom.Document;  
  6. import org.jdom.Element;  
  7. import org.jdom.input.SAXBuilder;  
  8. import org.jdom.xpath.XPath;  
  9.   
  10. import com.tgb.container.dao.Dao;  
  11. import com.tgb.container.service.Service;  
  12.   
  13. /** 
  14.  * 从类路径加载配置文件 
  15.  *  
  16.  * @author liang 
  17.  *  
  18.  */  
  19. public class ClassPathXmlApplicationContext implements BeanFactory {  
  20.   
  21.     // 用于存放Bean  
  22.     private Map<String, Object> beans = new HashMap<String, Object>();  
  23.   
  24.     public ClassPathXmlApplicationContext(String fileName) {  
  25.   
  26.         this.readXML(fileName);  
  27.   
  28.     }  
  29.   
  30.     // 解析xml文件,通过反射将配置的beasn放到container中,并实现依赖注入  
  31.     private void readXML(String fileName) {  
  32.         // 创建SAXBuilder对象  
  33.         SAXBuilder saxBuilder = new SAXBuilder();  
  34.         // 读取资源,获得document对象  
  35.         Document doc;  
  36.         try {  
  37.             doc = saxBuilder.build(this.getClass().getClassLoader().getResourceAsStream(fileName));  
  38.   
  39.             // 获取根元素  
  40.             Element rootEle = doc.getRootElement();  
  41.             // 从根元素获得所有的子元素,建立元素集合  
  42.             List listBean = XPath.selectNodes(rootEle, "/beans/bean");  
  43.   
  44.             // 遍历根元素的子元素集合,扫描配置文件中的bean  
  45.             for (int i = 0; i < listBean.size(); i++) {  
  46.                 Element bean = (Element) listBean.get(i);  
  47.                 // 获取id属性值  
  48.                 String id = bean.getAttributeValue("id");  
  49.                 // 获取class属性值  
  50.                 String clazz = bean.getAttributeValue("class");  
  51.                 // 反射,实例化  
  52.                 Object o = Class.forName(clazz).newInstance();  
  53.                 beans.put(id, o);  
  54.             }  
  55.   
  56.             // 依赖管理,这里还不灵活,但是原理是一样的  
  57.             Service service = (Service) beans.get("service");  
  58.             Dao dao = (Dao) beans.get("dao");  
  59.             // 依赖注入,Service实现依赖dao的实现  
  60.             service.setDao(dao);  
  61.   
  62.         } catch (Exception e) {  
  63.   
  64.             e.printStackTrace();  
  65.         }  
  66.     }  
  67.   
  68.     /** 
  69.      * 查找组件 
  70.      *  
  71.      * @param id 
  72.      * @return 
  73.      */  
  74.     @Override  
  75.     public Object getBean(String id) {  
  76.         return beans.get(id);  
  77.     }  
  78. }  

     看到上面的代码,我们发现读取配置文件的方法中包含了反射,代码的可读性太差,并且对面向对象的封装不够彻

底,下面我们将bean的实例化以及依赖注入进行进一步的封装。


封装bean的实例化


       为了做进一步的封装,我们将配置文件的属性封装成一个javabean,为了存放我们的属性值。如下所示:

[java]  view plain copy print ? 在CODE上查看代码片 派生到我的代码片
  1. public class BeanDefinition {  
  2.   
  3.     private String id;  
  4.     private String className;  
  5.   
  6.       
  7.     public BeanDefinition(String id, String className) {  
  8.         this.id = id;  
  9.         this.className = className;  
  10.     }  
  11.   
  12.     public String getId() {  
  13.         return id;  
  14.     }  
  15.   
  16.     public void setId(String id) {  
  17.         this.id = id;  
  18.     }  
  19.   
  20.     public String getClassName() {  
  21.         return className;  
  22.     }  
  23.   
  24.     public void setClassName(String className) {  
  25.         this.className = className;  
  26.     }  
  27.   
  28. }  

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

[java]  view plain copy print ? 在CODE上查看代码片 派生到我的代码片
  1. import java.util.ArrayList;  
  2. import java.util.HashMap;  
  3. import java.util.List;  
  4. import java.util.Map;  
  5.   
  6. import org.jdom.Document;  
  7. import org.jdom.Element;  
  8. import org.jdom.input.SAXBuilder;  
  9. import org.jdom.xpath.XPath;  
  10.   
  11. import com.tgb.container.dao.Dao;  
  12. import com.tgb.container.service.Service;  
  13.   
  14. /** 
  15.  * 容器 
  16.  *  
  17.  * @author liang 
  18.  *  
  19.  */  
  20. public class ClassPathXmlApplicationContext implements BeanFactory {  
  21.   
  22.     // 用于存放Bean  
  23.     private List<BeanDefinition> beanDefines = new ArrayList<BeanDefinition>();  
  24.     // 用于存放Bean的实例  
  25.     private Map<String, Object> sigletons =new HashMap<String, Object>();  
  26.       
  27.       
  28.     public ClassPathXmlApplicationContext(String fileName) {  
  29.   
  30.         this.readXML(fileName);  
  31.           
  32.         this.instanceBeans();  
  33.           
  34.         this.injectObject();  
  35.     }  
  36.   
  37.     /** 
  38.      * 依赖注入,为bean对象的属性注入值 
  39.      * 这里还不灵活,但是原理是一样的 
  40.      */  
  41.     private void injectObject() {  
  42.         Service service = (Service) this.sigletons.get("service");  
  43.         Dao dao = (Dao) this.sigletons.get("dao");  
  44.         //依赖注入,Service实现依赖dao的实现  
  45.         service.setDao(dao);  
  46.     }  
  47.   
  48.     /** 
  49.      * 完成bean的实例化 
  50.      */  
  51.     private void instanceBeans() {  
  52.         for(BeanDefinition beanDefinition : beanDefines){  
  53.             try {  
  54.                 if(beanDefinition.getClassName() != null && !"".equals(beanDefinition.getClassName().trim())){  
  55.                     sigletons.put(beanDefinition.getId(),Class.forName(beanDefinition.getClassName()).newInstance() );  
  56.                 }  
  57.             } catch (Exception e) {  
  58.                 e.printStackTrace();  
  59.             }  
  60.         }  
  61.     }  
  62.   
  63.     /** 
  64.      * 读取xml配置文件 
  65.      */  
  66.     private void readXML(String fileName) {  
  67.         // 创建SAXBuilder对象  
  68.         SAXBuilder saxBuilder = new SAXBuilder();  
  69.   
  70.         try {  
  71.             // 读取资源,获得document对象  
  72.             Document doc = saxBuilder.build(this.getClass().getClassLoader()  
  73.                     .getResourceAsStream(fileName));  
  74.             // 获取根元素  
  75.             Element rootEle = doc.getRootElement();  
  76.             // 从根元素获得所有的子元素,建立元素集合  
  77.             List listBean = XPath.selectNodes(rootEle, "/beans/bean");  
  78.   
  79.             // 遍历根元素的子元素集合,扫描配置文件中的bean  
  80.             for (int i = 0; i < listBean.size(); i++) {  
  81.                 Element bean = (Element) listBean.get(i);  
  82.                 // 获取id属性值  
  83.                 String id = bean.getAttributeValue("id");  
  84.                 // 获取class属性值  
  85.                 String clazz = bean.getAttributeValue("class");  
  86.                   
  87.                 BeanDefinition beanDefine = new BeanDefinition(id,clazz);  
  88.                 // 将javabean添加到集合中  
  89.                 beanDefines.add(beanDefine);  
  90.             }  
  91.         } catch (Exception e) {  
  92.             e.printStackTrace();  
  93.         }  
  94.     }  
  95.   
  96.   
  97.     /** 
  98.      * 获取bean实例 
  99.      */  
  100.     @Override  
  101.     public Object getBean(String beanName) {  
  102.         return this.sigletons.get(beanName);  
  103.     }  
  104.   
  105. }  

      我们知道容器不仅负责创建对象,而且可以管理对象的依赖关系,管理对象的生命周期等等。我们仅实现了容器

灵活创建对象的部分,依赖注入部分是由我们手动注入的。 对象的依赖关系还不灵活,但是我们已经能够看到IoC的

影子了,只是形似,还没有达到神似的目标。

      下篇博文【SSH进阶之路】一步步重构容器实现Spring框架——彻底封装,实现简单灵活的Spring框架(十一),马

上送上。


     源码下载

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值