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

实现自己的Ioc容器

程序员文章站 2022-07-14 17:12:26
...
   ioc概念原理就不在细说了,知道java反射的话理解并实现一个简单的Ioc其实很简单,现在很多框架都会用到反射,还有框架中的工厂模式,基本都离不开反射,所以做为一个java程序员掌握反射的基本用法是一个基本的要求。

  废话不多说直接上程序,下面程序是实现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());
	}
}