一聚教程网:一个值得你收藏的教程网站

热门教程

用java的spring实现一个简单的IOC容器示例代码

时间:2022-06-29 01:31:34 编辑:袖梨 来源:一聚教程网

要想深入的理解IOC的技术原理,没有什么能比的上我们自己实现它。这次我们一起实现一个简单IOC容器。让大家更容易理解Spring IOC的基本原理。

这里会涉及到一些java反射的知识,如果有不了解的,可以自己去找些资料看看。

注意

在上一篇文章,我说,启动IOC容器时,Spring会将xml文件里面配置的bean扫描并实例化,其实这种说法不太准确,所以我在这里更正一下,xml文件里面配置的非单利模式的bean,会在第一次调用的时候被初始化,而不是启动容器的时候初始化。但是我们这次要做的例子是容器启动的时候就将bean初始化。特此说明一下,害怕误导初学者。

现在我们开始做一个简单的IOC容器

思路:

1,启动容器时,加载xml文件。

2,读取xml文件内的bean信息,并使用反射技术将bean实例化,并装入容器。

3,确认bean之间的以来关系,进行注入。

下面直接上代码,先看配置文件,与上一篇文章中使用的例子是一样的,我们这次继续使用上一篇文章的吃苹果和吃橘子的例子,只不过这次我们用我们自己写的IOC容器,所以,我只粘贴了关键代码。

 

 代码如下复制代码

xml version="1.0" encoding="UTF-8"?>
<beans>
    
  <bean id="eatOrange" class="it.spring.liao.com.EatOrange">bean>
    
  <bean id="eatApple" class="it.spring.liao.com.EatApple">bean>
  <bean id="person" class="it.spring.liao.com.Person">
    
    <property name="eat" ref="eatOrange"/>
  bean>
beans>


 

此处为关键代码

 

 代码如下复制代码

packageit.spring.liao.com;

 

importjava.io.InputStream;

importjava.lang.reflect.Method;

importjava.util.HashMap;

importjava.util.Iterator;

importjava.util.Map;

 

importorg.dom4j.Attribute;

importorg.dom4j.Document;

importorg.dom4j.Element;

importorg.dom4j.io.SAXReader;

 

publicclassBeanFactory {

 

  // 用于存放bean实例的集合

  privateMapbeanMap =newHashMap();

 

  /**

   * bean工厂的初始化.

   *

   * @param xml

   *      配置文件路径

   */

  publicvoidinit(String xml) {

    try{

      // 1.创建读取配置文件的reader对象

      SAXReader reader =newSAXReader();

      // 2.获取当前线程中的类装载器对象

      ClassLoader classLoader = Thread.currentThread().getContextClassLoader();

      // 3.从class目录下获取指定的xml文件

      InputStream ins = classLoader.getResourceAsStream(xml);

      // 4.使用dom4j 解析xml文件

      Document doc = reader.read(ins);

      Element root = doc.getRootElement();

      // 5.初始化bean

      setBean(root);

      // 6.注入bean的依赖关系

      setPv(root);

    }catch(Exception e) {

      System.out.println(e.toString());

    }

  }

 

  /**

   * 初始化bean

   *

   * @param root

   *      xml文件

   * @throws Exception

   */

  publicvoidsetBean(Element root)throwsException {

    // 1.遍历xml文件当中的Bean实例

    for(Iterator i = root.elementIterator("bean"); i.hasNext();) {

      Element foo = (Element) i.next();

      // 2.针对每个Bean实例,获取bean的属性id和class

      String id = foo.attribute("id").getText();

      String cls = foo.attribute("class").getText();

      // 3.利用Java反射机制,通过class的名称获取Class对象

      Class bean = Class.forName(cls);

      // 4.创建对象

      Object obj = bean.newInstance();

      // 5.将对象放入beanMap中,其中key为bean的id值,value为bean的实例

      beanMap.put(id, obj);

    }

  }

 

  /**

   * 注入bean的依赖关系

   *

   * @param root

   *      xml文件

   * @throws Exception

   */

  publicvoidsetPv(Element root)throwsException {

    for(Iterator it = root.elementIterator("bean"); it.hasNext();) {

      Element foo = (Element) it.next();

 

      // 1.针对每个Bean实例,获取bean的属性id和class

      String cls = foo.attribute("class").getText();

      String id = foo.attribute("id").getText();

 

      // 2.利用Java反射机制,通过class的名称获取Class对象

      Class bean1 = Class.forName(cls);

 

      // 3.获取对应class的信息

      java.beans.BeanInfo info = java.beans.Introspector.getBeanInfo(bean1);

 

      // 4.获取其属性描述

      java.beans.PropertyDescriptor pd[] = info.getPropertyDescriptors();

 

      // 5遍历该bean的property属性

      for(Iterator ite = foo.elementIterator("property"); ite.hasNext();) {

        Element foo2 = (Element) ite.next();

 

        // 6.获取该property的name属性

        String name = foo2.attribute("name").getText();

        String ref = foo2.attribute("ref").getText();

 

        // 7.在类中寻找与xml配置文件中该bean的property属性名相同的属性

        for(intk =0; k < pd.length; k++) {

          // 8.如果相等,证明已经找到对应得属性

          if(pd[k].getName().equalsIgnoreCase(name)) {

            Method mSet =null;

            // 9.利用反射,获取该属性的set方法

            mSet = pd[k].getWriteMethod();

            // 10.用原beanMap中该bean的实例,执行该属性的set方法,并从原beanMap中获取该属性的依赖值

            mSet.invoke(beanMap.get(id), beanMap.get(ref));

          }

        }

        break;

      }

    }

  }

 

  /**

   * 通过bean的id获取bean的实例

   *

   * @param beanName

   *      bean的id

   * @return 返回对应对象

   */

  publicObject getBean(String beanName) {

    Object obj = beanMap.get(beanName);

    returnobj;

  }

 

}

 

 

 

 

  /**

   * 测试方法.

   *

   * @param args

   */

  publicstaticvoidmain(String[] args) {

    //使用我们自己写的 BeanFactory

    BeanFactory factory =newBeanFactory();

    factory.init("eat.xml");

    Person javaBean = (Person) factory.getBean("person");

    System.out.println(javaBean.eat());

  }

 

详细的解释都在代码的注释中,这个例子可以帮助你更深刻的理解spring的基本技术原理。但Spring的复杂程度远远高于这个例子,再说一次,spring  IOC中使用懒加载机制,在启动spring  IOC时,只会实例化单例模式的bean,不会实例化普通的bean,关于单例模式还是其他模式,是可以自己配置的,我们会在后面的文章中讲解,非单例模式bean的实例化,发生在第一次调用的时候,与我们这个例子不太一样。这个例子只供了解Spring  IOC的基本原理,真实情况要复杂的多,需要我们一点点的去学习,不积跬步无以至千里。

热门栏目