实现自己的Ioc容器
程序员文章站
2022-07-14 17:12:26
...
ioc概念原理就不在细说了,知道java反射的话理解并实现一个简单的Ioc其实很简单,现在很多框架都会用到反射,还有框架中的工厂模式,基本都离不开反射,所以做为一个java程序员掌握反射的基本用法是一个基本的要求。
废话不多说直接上程序,下面程序是实现ioc的核心部分,用到的配置文件还有其它类都在附件中,这个程序仅实现了ioc的依赖注入功能,比较简单主要用到技术有xml解析及反射。
在test包中有单元测试一个是反射的单元测试,一个是依赖注入的单元测试,运行时候需要自己导入junit包。
(这代码其实是在2012年写的,最近给项目组分享ioc原理及实现,又翻出来了,做演示用。:oops: )
废话不多说直接上程序,下面程序是实现ioc的核心部分,用到的配置文件还有其它类都在附件中,这个程序仅实现了ioc的依赖注入功能,比较简单主要用到技术有xml解析及反射。
在test包中有单元测试一个是反射的单元测试,一个是依赖注入的单元测试,运行时候需要自己导入junit包。
(这代码其实是在2012年写的,最近给项目组分享ioc原理及实现,又翻出来了,做演示用。:oops: )
package com.factory; 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; import com.ioc.bean.Book; import com.ioc.bean.User; public class BeanFactory { private static Map<String, Object> beanMap = new HashMap<String, Object>(); /** * bean工厂的初始化,并进行属性注入 * * @param xml * */ @SuppressWarnings("unchecked") public void init(String xml) { try { //从class目录下获取指定的xml文件 ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); InputStream ins = classLoader.getResourceAsStream(xml); //解析xml SAXReader reader = new SAXReader(); Document doc = reader.read(ins); Element root = doc.getRootElement(); Element beanNode; //遍历bean for (Iterator i = root.elementIterator("bean"); i.hasNext();) { beanNode = (Element) i.next(); // 获取bean的属性id和class Attribute id = beanNode.attribute("id"); Attribute className = beanNode.attribute("class"); //利用Java反射机制,通过class的名称获取Class对象 Class beanClass = Class.forName(className.getText()); //实例化对象 Object obj = beanClass.newInstance(); //设置对象属性值 setBeanProperty(beanNode,beanClass,obj); // 将对象放入beanMap中,其中key为id值,value为对象 beanMap.put(id.getText(), obj); } } catch (Exception e) { System.out.println(e.toString()); e.printStackTrace(); } } //设置对象属性值 @SuppressWarnings("unchecked") private static void setBeanProperty(Element beanNode,Class beanClass,Object obj) throws Exception{ // 设置值的方法 Method method = null; // 获取对应class的信息 java.beans.BeanInfo beanInfo = java.beans.Introspector.getBeanInfo(beanClass); // 获取其属性描述 java.beans.PropertyDescriptor proDescriptor[] = beanInfo.getPropertyDescriptors(); // 遍历该bean的property属性 for (Iterator ite = beanNode.elementIterator("property"); ite.hasNext();) { Element beanPro = (Element) ite.next(); // 获取该property的name属性 Attribute name = beanPro.attribute("name"); Attribute ref = beanPro.attribute("ref"); Object proVal = null; if(ref!=null){ proVal=beanMap.get(ref.getValue()); }else{ // 获取该property的子元素value的值 for (Iterator ite1 = beanPro.elementIterator("value"); ite1.hasNext();) { Element node = (Element) ite1.next(); proVal = node.getText(); break; } } for (int k = 0; k < proDescriptor.length; k++) { if (proDescriptor[k].getName().equalsIgnoreCase(name.getText())) { method = proDescriptor[k].getWriteMethod(); // 利用Java的反射极致调用对象的某个set方法,并将值设置进去 method.invoke(obj, proVal); } } } } /** * * 通过bean的id获取bean的对象. * * * @param beanName * bean的id * * @return 返回对应对象 */ public static Object getBean(String beanName) { Object obj = beanMap.get(beanName); return obj; } static{ BeanFactory factory = new BeanFactory(); factory.init("config.xml"); } /** * * 测试方法. * */ public static void main(String[] args) { User userBean = (User) BeanFactory.getBean("userBean"); System.out.println("userName=" + userBean.getUserName()); System.out.println("password=" + userBean.getPassword()); System.out.println("password=" + userBean.getBook().getBookName()); Book bookBean=(Book)BeanFactory.getBean("bookBean"); System.out.println("bookName=" + bookBean.getBookName()); } }
上一篇: jCT 3.9.12.10 放出,大改变,文档重新发布
下一篇: Handler倒计时跳转