欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

模拟实现IoC容器

程序员文章站 2022-04-14 20:27:19
Spring的IoC核心就是控制反转,将对实现对象的操作控制器交出来,由IoC容器来管理,从配置文件中获取配置信息,Java对XML文档提供了完美的支持,dom4j功能强大,而下面我就用JDOM这一开源项目,利用它可以纯Java技术实现对XML文档的解析、生成、序列化来模拟实现IoC容器。 一、传统 ......

       spring的ioc核心就是控制反转,将对实现对象的操作控制器交出来,由ioc容器来管理,从配置文件中获取配置信息,java对xml文档提供了完美的支持,dom4j功能强大,而下面我就用jdom这一开源项目,利用它可以纯java技术实现对xml文档的解析、生成、序列化来模拟实现ioc容器。

 一、传统方式完成项目。
        1.定义接口

package com.decipher.car;

public interface car {
    public string getbrand();
    public void run();
    
}


2.接下来实现car接口

package com.decipher.carimplementation;
import com.decipher.car.car;
public class bmwcar implements car{
    private string mybrand="宝马";
    public string getbrand(){
        return mybrand;
    }
    public void run(){
        system.out.println(mybrand+" is runing");
    }
}


3.新建一个human类

package com.decipher.human;
import com.decipher.car.car;
public class human {
    private car car;

    public car getcar() {
        return car;
    }

    public void setcar(car car) {
        this.car = car;
    }
    public void mycarrun(){
        car.run();
    }
}


4.最后编写测试类

package com.decipher.humen;

import com.decipher.car.car;
import com.decipher.carimplementation.bmwcar;
import com.decipher.human.human;

public class humentest {
    public static void main(string[] args) throws exception {
        human human=new human();
        car car=new bmwcar();
        human.setcar(car);
        human.mycarrun();    
    }
}

 


5.运行结果如图:
模拟实现IoC容器


二.jdom模拟ioc容器反转控制
在编程之前要导入jdom.jar包到项目工程目录中。
1.新建beanfactory

package com.decipher.spring;

public interface beanfactory {
    public object getbean(string id);
}

 


2.实现beanfactory接口

package com.decipher.spring;

import java.lang.reflect.method;
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;

public class classpathxmlapplicationcontext {
    //储存各个实例的键值对
    private map<string,object> beans=new hashmap<string,object>();
    //构造方法
    public classpathxmlapplicationcontext() throws exception{
        //读取xml文档
        saxbuilder sb=new saxbuilder();
        //构造文档对象doc
        document doc=sb.build(this.getclass().getclassloader().getresource("beans.xml"));
        //获取xml文档根元素
        element root=doc.getrootelement();
        //获取根元素下所有的子元素
        list list=root.getchildren("bean");
        //遍历所有的bean元素
        for(int i=0;i<list.size();i++){
            //取得第i个bean元素
            element element=(element)list.get(i);
            //获取第i个bean元素的id属性值,并将其存入到字符串变量id中
            string id=element.getattributevalue("id");
            //获取第i个bean元素的class属性值,并将其存入到字符串变量clazz中
            string clazz=element.getattributevalue("class");
            //使用反射生成类的对象,相当于生成类对象,且存储在map中
            object o=class.forname(clazz).newinstance();
            system.out.println(id);
            system.out.println(clazz);
            beans.put(id,o);//将id和对象o存入map中
            //对第i个bean元素下的每个property子元素进行遍历
            for(element propertyelement:(list<element>)element.getchildren("property")){
                //获取property元素的name属性值
                string name=propertyelement.getattributevalue("name");
                //获取property元素的bean属性值
                string beaninstance=propertyelement.getattributevalue("bean");
                //取得被注入对象的实例
                object beanobject=beans.get(beaninstance);
                //获取setter方法的方法名,形式为setxxx
                string methodname="set"+name.substring(0, 1).touppercase()+name.substring(1);
                system.out.println("method name= "+methodname);
                //使用反射取得指定名称,指定参数类型的setxxx方法
                method m=o.getclass().getmethod(methodname, beanobject.getclass().getinterfaces()[0]);
                //调用对象o的setxxx方法
                m.invoke(o,beanobject);
            }
        }
    }
        public object getbean(string id){
            return beans.get(id);
        }
}

 


3.配置beans.xml文件

<beans>
    <bean id="baomacar" class="com.decipher.carimplementation.bmwcar">
    </bean>
    <bean id="human" class="com.decipher.human.human">
        <property name="car" bean="baomacar"></property>
    </bean>
</beans>

 


4.编写测试类humentest

package com.decipher.humen;

import com.decipher.spring.classpathxmlapplicationcontext;
import com.decipher.car.car;
import com.decipher.carimplementation.bmwcar;
import com.decipher.human.human;

public class humentest {
    public static void main(string[] args) throws exception {    
        classpathxmlapplicationcontext ctx=new classpathxmlapplicationcontext();
        human human=(human)ctx.getbean("human");
        human.mycarrun();
    }
}

 


5.运行如图:
模拟实现IoC容器

6.总结
    从上面的两种实例化对象可以看出,传统的方式中,由程序员管理类对象,而在模拟的ioc容器中,将对类对象操作的控制器移交给ioc容器,由ioc容器中的applicationcontext处理xml配置文件,xml文件中每配置一个bean,即存储在map中,不需要程序员再new一个对象,而直接从容器中获取即可,控制反转可以松耦,交出控制权利。