简单IOC容器实现

作为spring框架中的重要思想,ioc(控制反转)是面试中的常客。关于如何理解ioc容器,可以通过自己实现一个简单的ioc容器来领会

步骤分析

简单来说,ioc就是实现了通过配置文件创建对象功能,核心部分就是依赖注入,实现步骤如下:

  1. 加载配置文件
  2. 遍历bean标签,获取id和class值
  3. 加载class类并创建bean
  4. 遍历 < property > 标签,把属性值填充到相关字段
  5. 把bean注册到容器当中

IOC容器实现类

直接看代码和注释:

private Map<String, Object> beanmap = new HashMap<String, Object>();    
public IOCDemo(String location) throws Exception {
  loadBeans(location); 
}    
private void loadBeans(String location) throws Exception {     
	// 读取配置文件  
	InputStream is = new FileInputStream(location);  
	// 读入.xml文档需要一个DocumentBuilder对象  
	DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();  
	DocumentBuilder docBuilder = factory.newDocumentBuilder();  
	// 通过java IO 流的读取文件  
	Document document = docBuilder.parse(is);  
	Element root = document.getDocumentElement();  
	NodeList nodes = root.getChildNodes();  
	// 遍历bean标签  
	for (int i = 0; i < nodes.getLength(); i++) {
	   Node node = nodes.item(i);   
	   if (node instanceof Element) {
	       Element e = (Element) node;    
	       String id = e.getAttribute("id");    
	       String classname = e.getAttribute("class");    
	       // 加载beanClass    
	       Class beanClass = null;    
	       beanClass = Class.forName(classname);    
	       // 创建bean    
	       Object bean = beanClass.newInstance();    
	       // 遍历  标签    
	       NodeList propertiesList = e.getElementsByTagName("property");    
	       for (int j = 0; j < propertiesList.getLength(); j++) {
	            Node propertyNode = propertiesList.item(j);     
	            if (propertyNode instanceof Element) {
	                  Element proElement = (Element) propertyNode;      
	                  String name = proElement.getAttribute("name");      
	                  String value = proElement.getAttribute("value");      
	                  // 利用反射将bean相关字段f访问权限设为可访问      
	                  Field declaredField = bean.getClass().getDeclaredField(name);      
	                  declaredField.setAccessible(true);      
	                  if (value != null && value.length() > 0) {       
	                  // 把属性值填充到相关字段
	                         declaredField.set(bean, value);      
	                  } else {
	                         String ref = proElement.getAttribute("ref");       
	                         if (ref == null || ref.length() == 0) {
	                                 throw new IllegalArgumentException("ref config error");       
	                         }       
	                         declaredField.set(bean, getBean(ref));     
	                  }      
	                  // 把bean注册到容器当中      
	         		beanmap.put(id, bean);     
	     		}
			}   
		}  
	} 
}

获取bean的方法:

public Object getBean(String name) {
  // TODO Auto-generated method stub
  Object bean = beanmap.get(name);
  if (bean == null) {
   throw new IllegalArgumentException("there is no bean with name " + name);
  }
  return bean;
 }

测试

接下来测试一下好不好使:

  1. 配置文件:
<bean id="computer" class="com.ioc.entry.Computer">
        <property name="name" value="拯救者 Y7000"/>
        <property name="weight" value="2.3kg"/>
        <property name="size" value="15.6英寸"/>
bean>
  1. 实体类
public class Computer {
	private String name;
	private String weight;
	private String size;
	//...省略get/set方法
}
  1. 测试类
		String location = IOCDemo.class.getClassLoader().getResource("resource/test.xml").getFile();
		IOCDemo demo = new IOCDemo(location);
		Computer computer = (Computer) demo.getBean("computer");
		System.out.println(computer);
  1. 结果

Computer [name=拯救者 Y7000, weight=2.3kg, size=15.6英寸]

  1. 完整例子

你可能感兴趣的:(总结)