Spring IoC的模拟实现

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文件。

假设我们的applicationContext.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>

可以看到,我们实现的Ioc应该能够产生一个名叫userDAO的com.SpringLearn.simulate.UserDAO的对象,和一个userService对象,且userService对象中的userDAO应该被初始化了,通过setUserDAO设置进去。

那么,既然可以用getBean获取所需的bean对象,那么我们就应该有一个BeanFactory接口。

package com.SpringLearn.simulate;
public interface BeanFactory {

	public Object getBean(String beanName);
}

那么有一个ClassPathXmlApplicationContext类实现BeanFactory接口。在其构造函数中,应首先读取xml文件,首先通过bean元素得知对象所属的类和对象的名字,然后再判断其下是否有property标签,如果有,那么获得property标签中ref指定的对象,再通过setxxxx(通过getClass().getMethod()反射实现)将其注入bean对象中。具体的代码如下所示:

package com.SpringLearn.simulate;
import java.io.IOException;
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;
//模拟spring中的一个关键的部分
public class ClassPathXmlApplicationContext implements BeanFactory{

	private Map<String,Object> map = new HashMap<String,Object>();
	
	//读取配置文件,进行初始化
	public ClassPathXmlApplicationContext() {
		
		SAXBuilder saxBuilder = new SAXBuilder();
		try {
			Document doc = saxBuilder.build("src/com/SpringLearn/simulate/applicationContext.xml");
			Element root = doc.getRootElement();
			List beans = root.getChildren("bean");
			for(int i=0;i<beans.size();i++){
				
				Element elem = (Element)beans.get(i);
				String id = elem.getAttributeValue("id");
				String beanName = elem.getAttributeValue("class");
				
				Object o = Class.forName(beanName).newInstance();
				//读取其下的子元素
				List list1 = elem.getChildren("property");
				for(int j=0;j<list1.size();j++){
					
					Element elem1 = (Element)list1.get(j);
					String name = elem1.getAttributeValue("name");
					String ref = elem1.getAttributeValue("ref");
					
					Object property = getBean(ref);
					Method method = o.getClass().getMethod("set"+name.substring(0,1).toUpperCase()+name.substring(1),property.getClass());
					method.invoke(o,property);
				}
				
				//放入map中
				map.put(id,o);
			}
			
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	public Object getBean(String beanName) {
		
		return map.get(beanName);
	}
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值