简单模拟Spring IOC功能

简单模拟了一下spring的注入功能,重点在于对这四点的把握。

第一点,XXContext类的理解和content对象的区别。

第二点, ClassPathXmlApplicationContext是BeanFactory的实现类。并且ClassPathXmlApplicationContext中定义了bean容器。(就是放所有的bean)

第三点,beanfactory的主要作用就是根据名字拿到相应的bean。

第四点,具体的注入本质就是反射调用SetBean方法,来为其赋值。

第五点,实际在spring中,beanfactory实现了bean的一些功能,但ClassPathXmlApplicationContext除了实现这些,还实现如控制bean生命周期等功能,所以,一般使用ClassPathXmlApplicationContext,但要知道,他是实现了beanfactory的。


具体每一点可见下面例子中的注释,userdao,userservice就不写了,只是userservice种有一个userdao属性,有get/set方法而已。

<beans>
  <bean id="userDaoImpl" class="springTest.dao.impl.UserDaoImpl"/>
  <bean id="userService" class="springTest.service.UserService" >
       <property name="userDao"  bean="userDaoImpl"></property>
  </bean>
</beans>

beanFactory类:

package springTest.spring;
/** 
 *  beanfactory的主要作用就是根据名字拿到相应的bean。
 */
public interface BeanFactory {
    public Object getBeans(String name);
}

ClassPathXmlApplicationContext类:

package springTest.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;

import test.lee.ReadXmlTest;

/**
 **************************
 ***一***XXContext类的理解***
 **************************
 *
 * XXContext类的理解和content对象的区别:
 *   1.XXContext类并不是说会产生content对象,而是会加载(利用)content对象。
 *   2.content对象     类似一个参数,XXContext类     类似一个方法。
 *   
 * 作用:
 *    这是策略模式的利用,其本质是赋值一些方法,就是 ClassPathXmlApplication类的一些方法的 赋值,而参数是这个content对象。 
 * 
 *  所以不要单纯的理解为上下文,其实质是 所有方法的 赋值。也可是说是上下文。
 *********************************************************************
 *********************************************************************
 ***二***要记住 ClassPathXmlApplicationContext是BeanFactory的实现类。***
 *********************************************************************
 *    它中定义了bean的容器
 *
 *    beanfactory的主要作用就是根据名字拿到相应的bean。
 *
 */
public class ClassPathXmlApplicationContext implements  BeanFactory {

	/**
	 * beans 就是一个map类型的容器,它存放所有的bean,
	 *       
	 *       1.在服务器启动的时候,初始化所有的bean。
	 *       2.把所有bean放到容器中去。     
	 *       3.用的时候,从容器中取出bean。  
	 *         注: 理解“取”   这个 取,其实就是注入了。在初始化一些bean时候,就会用到另一些bean,这其实就是取出。 
	 *
	 * 为bean中属性初始化bean的思路
	 * 
	 *       1.首先,把所有bean都放到容器中。
	 *       2.通过配置文件获取到bean的要注入的bean。也就是property。得到注入bean。
	 *       3.通过name设置setBean的方法。(主要是字符串处理)
	 *       4.通过反射调用setBean方法,为其注入。实现赋值。
	 */
	private Map<String,Object> beans = new HashMap<String,Object>();
	
	
	
	
	public ClassPathXmlApplicationContext() throws JDOMException, IOException, InstantiationException, IllegalAccessException, ClassNotFoundException, SecurityException, NoSuchMethodException, IllegalArgumentException, InvocationTargetException {
		
		SAXBuilder sb = new SAXBuilder();
		Document doc = sb.build(ReadXmlTest.class.getClassLoader().getResourceAsStream("beans.xml")); // 构造文档对象
		Element root = doc.getRootElement(); // 获取根元素
		List list = root.getChildren("bean");// 取名字为bean的所有元素
		for (int i = 0; i < list.size(); i++) {
			Element element = (Element) list.get(i);//获得一个bean
			String id = element.getAttributeValue("id");   //获得bean的属性值
			String clazz = element.getChildText("class");// 取bean子元素class的内容
			System.out.println(id+":"+clazz);
			Object o = Class.forName(clazz).newInstance();//建立bean对象
			beans.put(id, o);//将bean放入容器                         
			
			//取到所有的 property
			for(Element properElement:(List<Element>)element.getChildren("property")){
				String name =properElement.getAttributeValue("name");
				String bean =properElement.getAttributeValue("bean");
				Object beanObject = beans.get(bean);
				
				//拼接字符串   方法名字 setXx()
				String methodName = "set"+ name.substring(0,1).toUpperCase()+name.substring(1);
				//利用 反射实现 该方法的调用
				//数组的作用是userDao接口的实现类 userDaoimpl,它可以实现多个接口,所以是数组
				Method m = o.getClass().getMethod(methodName, beanObject.getClass().getInterfaces()[0]);
				m.invoke(o, beanObject);
			}
		}
	}


	@Override
	public Object getBeans(String name) {
		// TODO Auto-generated method stub
		return beans.get(name);
	}

	
	
	
}


总结一下,bean的使用呢,首先是放到一个容器里,所以要知道这一点。其次要明白,注入的那个bean,是通过反射调用set方法实现的,所以一定要写set方法。最后呢,是对策略模式的理解,放在这里,就是要知道,Context实现了beanfactory接口,完成了把他放入容器和发射调用SET注入两个功能。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

良之才-小良

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值