zoukankan      html  css  js  c++  java
  • Spring IOC容器解析及实现原理

    最近一段时间,“容器”两个字一直萦绕在我的耳边,甚至是吃饭、睡觉的时候都在我脑子里蹦来蹦去的。随着这些天一次次的交流、讨论,对于容器的理解也逐渐加深。理论上的东西终归要落实到实践,今天就借助spring容器实现原理,简单说说吧。

    简单的说,Spring就是通过工厂+反射将我们的bean放到它的容器中的,当我们想用某个bean的时候,只需要调用getBean("beanID")方法。

    原理简单介绍:

    Spring容器的原理,其实就是通过解析xml文件,或取到用户配置的bean,然后通过反射将这些bean挨个放到集合中,然后对外提供一个getBean()方法,以便我们获得这些bean。下面是一段简单的模拟代码:

    [java] view plain copy
     
     在CODE上查看代码片派生到我的代码片
    1. package com.tgb.spring.factory;  
    2.   
    3. import java.util.HashMap;  
    4. import java.util.List;  
    5. import java.util.Map;  
    6.   
    7. import org.jdom.Document;  
    8. import org.jdom.Element;  
    9. import org.jdom.input.SAXBuilder;  
    10. import org.jdom.xpath.XPath;  
    11.   
    12. public class ClassPathXmlApplicationContext implements BeanFactory  {  
    13.       
    14.     //容器的核心,用来存放注入的Bean  
    15.     private Map<String, Object> container = new HashMap<String, Object>();  
    16.       
    17.     //解析xml文件,通过反射将配置的bean放到container中  
    18.     public ClassPathXmlApplicationContext(String fileName) throws Exception{  
    19.         SAXBuilder sb = new SAXBuilder();  
    20.         Document doc = sb.build(this.getClass().getClassLoader().getResourceAsStream(fileName));  
    21.         Element root = doc.getRootElement();  
    22.         List list = XPath.selectNodes(root, "/beans/bean");  
    23.             
    24.         //扫描配置文件中的bean  
    25.         for (int i = 0; i < list.size(); i++) {              
    26.            Element bean = (Element) list.get(i);  
    27.            String id = bean.getAttributeValue("id");  
    28.            String clazz = bean.getAttributeValue("class");  
    29.            Object o = Class.forName(clazz).newInstance();  
    30.            container.put(id, o);  
    31.           }  
    32.     }  
    33.       
    34.     @Override  
    35.     public Object getBean(String id) {        
    36.         return container.get(id);  
    37.     }  
    38.   
    39. }  

    首先声明一个存放bean的Map,然后通过jdom解析配置文件,循环遍历所有的<bean>节点,并通过反射将它们放到我们之前声明的Map中。然后提供一个getBean()的方法,让我们可以通过bean的Id来找到我们想要的bean。

    下面是一个简单的xml配置文件:

    [html] view plain copy
     
     在CODE上查看代码片派生到我的代码片
    1. <?xml version="1.0" encoding="UTF-8"?>  
    2. <beans>  
    3.   
    4.   <bean id="E" class="com.tgb.spring.factory.England" />  
    5.     
    6.   <bean id="S" class="com.tgb.spring.factory.Spain" />  
    7.     
    8.   <bean id="P" class="com.tgb.spring.factory.Portugal" />  
    9.   
    10. </beans>  



    客户端通过调用前面的ClassPathXmlApplicationContext,来加载上面的配置文件,然后就可以通过Id来获得我们需要的bean了:

    [java] view plain copy
     
     在CODE上查看代码片派生到我的代码片
    1. package com.tgb.spring.factory;  
    2.   
    3. public class Test {  
    4.   
    5.     public static void main(String[] args) throws Exception {  
    6.           
    7.         //加载配置文件  
    8.         BeanFactory f = new ClassPathXmlApplicationContext("applicationContext.xml");  
    9.           
    10.         //英格兰  
    11.         Object oe = f.getBean("E");  
    12.         Team e = (Team)oe;  
    13.         e.say();  
    14.           
    15.         //西班牙  
    16.         Object os = f.getBean("S");  
    17.         Team s = (Team)os;  
    18.         s.say();  
    19.           
    20.         //葡萄牙  
    21.         Object op = f.getBean("P");  
    22.         Team p = (Team)op;  
    23.         p.say();  
    24.     }  
    25.   
    26. }  


    输出结果:

    [plain] view plain copy
     
     在CODE上查看代码片派生到我的代码片
    1. England :我们是欧洲的中国队,不在乎这次小组没出线...  
    2. Spain   :我们是两届欧洲杯冠军、一届世界杯冠军!  
    3. Portugal:我们的C罗一个顶十个!  


    其他代码:

    [java] view plain copy
     
     在CODE上查看代码片派生到我的代码片
    1. //工厂接口  
    2. package com.tgb.spring.factory;  
    3.   
    4. public interface BeanFactory {  
    5.     Object getBean(String id);  
    6. }  
    7.   
    8. //Team接口  
    9. package com.tgb.spring.factory;  
    10.   
    11. public interface Team {  
    12.     void say();  
    13. }  
    14.   
    15. //英格兰  
    16. package com.tgb.spring.factory;  
    17.   
    18. public class England implements Team{  
    19.       
    20.     public void say() {  
    21.         System.out.println("England:我们是欧洲的中国队,不在乎这次小组没出线...");  
    22.     }  
    23. }  
    24.   
    25. //西班牙  
    26. package com.tgb.spring.factory;  
    27.   
    28. public class Spain implements Team{  
    29.   
    30.     @Override  
    31.     public void say() {  
    32.         System.out.println("Spain:我们是两届欧洲杯冠军、一届世界杯冠军!");  
    33.     }  
    34.       
    35. }  
    36.   
    37. //葡萄牙  
    38. package com.tgb.spring.factory;  
    39.   
    40. public class Portugal implements Team {  
    41.   
    42.     @Override  
    43.     public void say() {  
    44.         System.out.println("Portugal:我们的C罗一个顶十个!");  
    45.     }  
    46.   
    47. }  


    以上内容是对Spring的一个简单模拟,当然Spring远比这个要复杂的多,也强大的多,而且获取bean的方式也不止通过工厂这一种。这里只是做一个粗略的Demo说说自己对容器的简单理解,向Spring致敬。例子简陋,表达粗糙,欢迎拍砖交流。

  • 相关阅读:
    CSS开发中常用技巧总结
    Linq的分组功能
    深入理解 C# 协变和逆变
    js数组删除数组元素!
    关于 Photoshop 蒙版和 Alpha 通道
    jQuery数组处理详解(含实例演示)
    多媒体指令(灰度像素最大值)
    多媒体指令(图像均值模糊)
    matlab练习程序(立体相关块匹配)
    matlab练习程序(steerable filters)
  • 原文地址:https://www.cnblogs.com/afjbk/p/5954985.html
Copyright © 2011-2022 走看看