Spring IOC的源码模拟

代码有备注,浅析易懂,别忘了项目中导入jdom.jar


Spring最重要的两大块,一个是依赖注入,另一个就是切面编程。其中,依赖注入用的范围更广。在WEB编程之中,通过xml来配置各个Bean之间的关系,使得开发过程更符合高内聚,低耦合的要求。

众所周知,使用Spring时,需要定义一个listener在web.xml文件中。当请求到达服务器是,根据listener,就会自动读取配置的applicationContext.xml文件。这个xml文件中主要配置了各个bean,那么就根据此xml文件,将所需要的bean都自动的生成出来,放在某一个容器中。那么在代码中,调用getBean(beanName)即可以获得所需要的bean,而不需要手动new。非常的方便。

通过对上面过程的理解,我们知道,要实现依赖注入,需要:1.解析xml文件 2.利用反射机制生成bean,并放入容器中,需要时再通过key值来取。第一个,我们可以用jdom来解析xml文件。

<?xml version="1.0" encoding="utf-8"?>
<beans>
	<bean id="userDAO" class="com.SpringLearn.simulate.UserDAO"/>
	<bean id="userService" class="com.SpringLearn.simulate.UserService">
		<property name="userDAO" ref="userDAO"/>
	</bean>
</beans>
package com.test.spring;

import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
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.JDOMException;
import org.jdom.input.SAXBuilder;

/**
 * @author 作者 E-mail:[email protected]
 * @version 创建时间:2015年3月7日 下午7:33:43
 * 类说明
 */
public class ClassPathXmlApplicationContext implements BeanFactory   {
	private Map<String, Object> beanMap = new HashMap<String, Object>();
	@Override
	public Object getBean(String beanName) {  
        
        return beanMap.get(beanName);  
    }  
	public void ClassPathXmlApplicationContext() throws Exception {
		   SAXBuilder saxBuilder = new SAXBuilder(); 
		    //加载整个文档
		   Document doc = saxBuilder.build("src/applicationContext.xml");
		   //加载root
		   Element rootElement = doc.getRootElement();
		   //获得所有的bean配置
		   List beans =rootElement.getChildren("bean");
		   //轮询所有的bean。挨个获取bean的位置
		   for (Object object : beans) {
			   Element elem = (Element)object;
			   String id = elem.getAttributeValue("id");
			   Object o = Class.forName(elem.getAttributeValue("class")).newInstance();
			   List  propertylist = elem.getChildren("property");
			   //轮询bean下的property的配置,对每个依赖进行注入,此处是调用set方法,
			   //类似于spring3中注入方式的构造方法注入
			   for (int i = 0; i < propertylist.size(); i++) {
				   Element e= (Element)propertylist.get(i);
				   String name = e.getAttributeValue("name");
				   String ref = e.getAttributeValue("ref");
				   //获得依赖的bean,准备注入
				   Object  property = getBean(ref);
				   //调用set方法注入,第一个参数是方法名,第二个参数是执行该方法的具体参数 ,此处property.getClass是指参数是个property配置的对象
				   Method method =o.getClass().getMethod("set"+name.substring(0,1).toUpperCase()+name.substring(1),property.getClass());
				   //执行获取的方法,并且传入要执行该方法的的对象O 和要传入的的参数property
				   method.invoke(o, property);
			}
			   beanMap.put(id, o);//模拟spring上下文,把所有Bean放入map中。需要的时候就从map中获取
		   
		   }
	}
	
	public static void main(String[] args) throws Exception {
		ClassPathXmlApplicationContext c = new ClassPathXmlApplicationContext();
	    c.ClassPathXmlApplicationContext();
	       UserService us =  (UserService)c.getBean("userService");
	    us.sayHelloAfterDao();
 		
	}
}

----------------------------------------------------------------------------

package com.test.spring;
/**
* @author 作者 E-mail:[email protected]
* @version 创建时间:2015年3月7日 下午7:29:13
* 类说明
*/

public class UserService {
	UserDAO userDAO ;
	public void setUserDAO(UserDAO userDAO) {
		this.userDAO = userDAO;
	}
   
 public void  sayHelloAfterDao() {
	 String s=  userDAO.say();
	System.out.println(s);
}
	

	
	
	
}

---------------------------------------------------------

package com.test.spring;
/**
* @author 作者 E-mail:[email protected]
* @version 创建时间:2015年3月7日 下午7:29:13
* 类说明
*/

public class UserDAO {
	public String say(){
		String s = "say hello";
		return s;
	}
	
	
}

-----------------------------------------------------

package com.test.spring;
public interface BeanFactory {  
  
    public Object getBean(String beanName);  
}


你可能感兴趣的:(Spring IOC的源码模拟)