首页 > 代码库 > spring IOC的实现原理

spring IOC的实现原理

姓名:罗秀群    班级:软件151

 IOC的意思是控件反转也就是由容器控制程序之间的关系,把控件权交给了外部容器,之前的写法,由程序代码直接操控,而现在控制权由应用代码中转到了外部容器,控制权的转移是所谓反转。

 IOC的一个重点是在系统运行中,动态的向某个对象提供它所需要的其他对象。这一点是通过DI(Dependency Injection,依赖注入)来实现的。

下面来模拟下IOC和DI的实现原理。

技术分享

1、首先定义DAO接口和接口的实现类
package com.dao;

public interface PersonDAO {
	public void save();
}
 
  1. package com.dao.impl;  
  2.   
  3. import com.dao.PersonDAO;  
  4.   
  5. public class PersonDaoImpl implements PersonDAO {  
  6.   
  7.     @Override  
  8.     public void save() {  
  9.         System.out.println("保存");  
  10.     }  
  11.   
2、创建一个Junit测试类
package com.test;

import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.dao.PersonDAO;
import com.myUtil.MyClassPathXmlApplicationContext;
import com.service.PersonService;


public class PersonTest {
	
	@Test
	public void instanceSpring1(){
		/**
		 * 
		 * spring 的实现
		 */
		//IOC
		ApplicationContext ac = new ClassPathXmlApplicationContext("beans.xml");
		PersonDAO pd = (PersonDAO) ac.getBean("personDAO");
		pd.save();
		//DI
		PersonService ps = (PersonService) ac.getBean("personService");
		ps.save();
	}
	
	@Test
	public void instanceSpring2(){
		
		/**
		 * 我的实现
		 * 
		 */
		MyClassPathXmlApplicationContext mac = new MyClassPathXmlApplicationContext("beans.xml");
		PersonDAO mpd = (PersonDAO) mac.getBean("personDAO");
		mpd.save();
		//DI
		PersonService ps = (PersonService) mac.getBean("personService");
		ps.save();
	}
	
}
方法instanceSpring1为Spring中的实现用到ClassPathXmlApplicationContext类,要实现IOC的原理要定义自己
的MyClassPathXmlApplicationContext首先读出beans.xml中的配置信息,通过反射机制实现bean,最后注入所需要的
bean。
package com.myUtil;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

public class MyClassPathXmlApplicationContext {
	// xml所有的属性
	private ArrayList<BeanDefinition> beanDefinitions = new ArrayList<BeanDefinition>();
	// xml中所有的bean
	private Map<String, Object> sigletons = new HashMap<String, Object>();

	public MyClassPathXmlApplicationContext(String file) {
		readXml(file);
		instanceBeans();
		instanceObject();
	}

	/**
	 * 注入
	 */
	private void instanceObject() {
		for (BeanDefinition beanDefinition : beanDefinitions) {
			//判断有没有注入属性
			if (beanDefinition.getProperty() != null) {
				Object bean = sigletons.get(beanDefinition.getId());
				if (bean != null) {
					try {
						//得到被注入bean的所有的属性
						PropertyDescriptor[] ps = Introspector.getBeanInfo(bean.getClass()).getPropertyDescriptors();
						//得到所有的注入bean属性
						for(PropertyDefinition propertyDefinition:beanDefinition.getProperty()){
							for(PropertyDescriptor propertyDescriptor:ps){
								if(propertyDescriptor.getName().equals(propertyDefinition.getName())){
									Method setter = propertyDescriptor.getWriteMethod();//获取set方法
									if(setter!=null){
										setter.setAccessible(true);//得到private权限
										//注入属性
										setter.invoke(bean, sigletons.get(propertyDefinition.getRef()));
									}
									break;
								}
							}
						}
					} catch (Exception e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}
			}
		}
	}

	/**
	 * 实例所有的bean
	 */
	private void instanceBeans() {
		for (int i = 0; i < beanDefinitions.size(); i++) {
			BeanDefinition bd = beanDefinitions.get(i);
			try {
				try {
					if (bd.getClassName() != null
							&& !bd.getClassName().equals(""))
						sigletons.put(bd.getId(), Class.forName(
								bd.getClassName()).newInstance());
				} catch (InstantiationException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				} catch (IllegalAccessException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			} catch (ClassNotFoundException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}

	/**
	 * 读xml
	 * 
	 * @param file
	 */
	private void readXml(String file) {
		try {
			SAXReader reader = new SAXReader(); // 使用SAX方式解析XML
			URL xmlPath = this.getClass().getClassLoader().getResource(file);
			Document doc = reader.read(xmlPath);
			Element root = doc.getRootElement(); // 取得根节点
			List<Element> beans = root.elements();
			for (Element element : beans) {
				String id = element.attributeValue("id");// id;
				String clazz = element.attributeValue("class");
				BeanDefinition bd = new BeanDefinition(id, clazz);
				// 读取子元素
				if (element.hasContent()) {
					List<Element> propertys = element.elements();
					for (Element property : propertys) {
						String name = property.attributeValue("name");
						String ref = property.attributeValue("ref");
						PropertyDefinition pd = new PropertyDefinition(name,
								ref);
						bd.getProperty().add(pd);
					}
				}
				beanDefinitions.add(bd);
			}
		} catch (Exception e) {
			// TODO: handle exception
		}
	}

	/**
	 * 通过名字得到bean
	 * 
	 * @param str
	 * @return
	 */
	public Object getBean(String str) {
		return sigletons.get(str);
	}

}
读取所的bean实体
 
package com.myUtil;

import java.util.ArrayList;
import java.util.List;

public class BeanDefinition {
	private String id;
	private String className;
	private List<PropertyDefinition> property = new ArrayList<PropertyDefinition>();

	public BeanDefinition(String id, String className) {
		super();
		this.id = id;
		this.className = className;
	}

	public String getId() {
		return id;
	}

	public void setId(String id) {
		this.id = id;
	}

	public String getClassName() {
		return className;
	}

	public void setClassName(String className) {
		this.className = className;
	}

	public List<PropertyDefinition> getProperty() {
		return property;
	}

	public void setProperty(List<PropertyDefinition> property) {
		this.property = property;
	}

}

注入属性实体
package com.myUtil;

public class PropertyDefinition {
	private String name;
	private String ref;

	public PropertyDefinition(String name, String ref) {
		this.name = name;
		this.ref = ref;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getRef() {
		return ref;
	}

	public void setRef(String ref) {
		this.ref = ref;
	}

}

业务接口和实现类
package com.service;

public interface PersonService {
	public void save();
}
package com.service.impl;

import com.dao.PersonDAO;
import com.service.PersonService;

public class PersonServiceImpl implements PersonService{
	private PersonDAO pdo;

	public PersonDAO getPdo() {
		return pdo;
	}

	public void setPdo(PersonDAO pdo) {
		this.pdo = pdo;
	}

	@Override
	public void save() {
		pdo.save();
	}
	
}
beans.xml配置
 
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <beans xmlns="http://www.springframework.org/schema/beans"  
  3.     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"     
  4.     xsi:schemaLocation="http://www.springframework.org/schema/beans  
  5.            http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">  
  6.             
  7.     <bean id="personDAO" class="com.dao.impl.PersonDaoImpl"></bean>  
  8.     <bean id="personService" class="com.service.impl.PersonServiceImpl">  
  9.         <property name="pdo" ref="personDAO"></property>  
  10.     </bean>  
  11. </beans>  




 

 

spring IOC的实现原理