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