当前位置: 移动技术网 > IT编程>开发语言>Java > 用java的spring实现一个简单的IOC容器示例代码

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

2019年07月22日  | 移动技术网IT编程  | 我要评论

要想深入的理解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"?>
<!doctype beans public "-//spring/dtd bean/en" 
"http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
    <!--这是吃橘子的bean -->
  <bean id="eatorange" class="it.spring.liao.com.eatorange"></bean>
    <!--这是吃苹果的bean -->
  <bean id="eatapple" class="it.spring.liao.com.eatapple"></bean>
  <bean id="person" class="it.spring.liao.com.person">
    <!-- 这里我们注入的是吃橘子的bean-->
    <property name="eat" ref="eatorange"/>
  </bean>
</beans>

此处为关键代码

package it.spring.liao.com;

import java.io.inputstream;
import java.lang.reflect.method;
import java.util.hashmap;
import java.util.iterator;
import java.util.map;

import org.dom4j.attribute;
import org.dom4j.document;
import org.dom4j.element;
import org.dom4j.io.saxreader;

public class beanfactory {

  // 用于存放bean实例的集合
  private map<string, object> beanmap = new hashmap<string, object>();

  /**
   * bean工厂的初始化. <br>
   * 
   * @param xml
   *      配置文件路径
   */
  public void init(string xml) {
    try {
      // 1.创建读取配置文件的reader对象
      saxreader reader = new saxreader();
      // 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
   */
  public void setbean(element root) throws exception {
    // 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
   */
  public void setpv(element root) throws exception {
    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 (int k = 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 返回对应对象
   */
  public object getbean(string beanname) {
    object obj = beanmap.get(beanname);
    return obj;
  }

}




  /**
   * 测试方法.
   * 
   * @param args
   */
  public static void main(string[] args) {
    //使用我们自己写的 beanfactory
    beanfactory factory = new beanfactory();
    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的基本原理,真实情况要复杂的多,需要我们一点点的去学习,不积跬步无以至千里。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持移动技术网。

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网