Spring管理bean的原理自定义实现
1、Spring通过BeanDefinition管理基于Spring的应用中的各种对象以及他们之间的相互依赖关系。BeanDefinition抽象了我们对Bean的定义,是让容器起作用的主要数据类型。 IoC容器是用来管理对象依赖关系的,对IoC容器来说,BeanDefinition就是对依赖反转模式中管理的对象依赖关系的数据抽象,也是容器实现依赖反转功能的核心数据结构,依赖反转功能都是围绕对这个BeanDefinition的处理上完成的。
?? 定义BeanDefinition:?
?
package com.wxy.bean;public class beanDefinition { private String id; private String className; public beanDefinition(String id, String className) { this.id = id; this.className = className; } /** * @return the id */ public String getId() { return id; } /** * @param id the id to set */ public void setId(String id) { this.id = id; } /** * @return the className */ public String getClassName() { return className; } /** * @param className the className to set */ public void setClassName(String className) { this.className = className; } }?
2、自定义IoC容器WxyClassPathXMLApplicationContext ,该容器实现三个功能:
?(1) BeanDefinition的resource定位:readXML();
?(2) BeanDefinition的载入和解析 :readXML();
?(3) BeanDefinition在IoC容器中的注册 instanceBeans();
package com.wxy.content; 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.XPath;import org.dom4j.io.SAXReader; import com.wxy.bean.BeanDefinition; /*** 自定义IoC容器 * BeanDefinition的resource定位:readXML();* BeanDefinition的载入和解析 :readXML();* BeanDefinition在IoC容器中的注册 instanceBeans();* @create-time 2011-8-10 上午09:19:17 * @revision $Id*/public class WxyClassPathXMLApplicationContext { //存放BeanDefinition的列表,在beans.xml中定义的bean可能不止一个 private final List<BeanDefinition> beanDefinitions = new ArrayList<BeanDefinition>(); //将类名作为索引,将创建的Bean对象存入到Map中 private final Map<String, Object> sigletons = new HashMap<String, Object>(); public WxyClassPathXMLApplicationContext(String fileName) { //读取xml配置文件 this.readXML(fileName); //实例化bean this.instanceBeans(); } /** * 读取XML配置文件,获取BeanDefinition内容,存入到beanDefinition列表中 * @param fileName xml配置文件名称 */ private void readXML(String fileName) { SAXReader saxReader = new SAXReader(); Document document = null; try { //通过类加载器获取Resource资源路径,实现BeanDefinition的resource定位 URL xmlPath = this.getClass().getClassLoader().getResource(fileName); //将xml读入到document中 document = saxReader.read(xmlPath); Map<String, String> nsMap = new HashMap<String, String>(); //加入命名空间 nsMap.put("ns", "http://www.springframework.org/schema/beans"); //创建beans/bean查询路径,注意:路径前要注明命名空间,便于解析 XPath xsub = document.createXPath("//ns:beans/ns:bean"); //设置命名空间 xsub.setNamespaceURIs(nsMap); //获取文档下的所有Bean节点 List<Element> beans = xsub.selectNodes(document); for (Element element : beans) { //获取id属性值 String id = element.attributeValue("id"); //获取class属性值 String clazz = element.attributeValue("class"); BeanDefinition beanDefinition = new BeanDefinition(id, clazz); //将新创建的BeanDefinition赌侠ing放入到BeanDeifnitions中 beanDefinitions.add(beanDefinition); } } catch (Exception e) { System.out.println(e.toString()); } } /** * 实例化bean,存入到sigletons中 */ private void instanceBeans() { for (BeanDefinition beanDefinition : beanDefinitions) { try { if (beanDefinition.getClassName() != null && !(beanDefinition.getClassName().isEmpty())) { //利用java反射机制,生成BeanDefinition实例,并将其注册到sigletons中 sigletons.put(beanDefinition.getId(), Class.forName( beanDefinition.getClassName()).newInstance()); } } catch (Exception e) { e.printStackTrace(); } } } /** * 根据ID名获取实例bean * return 返回一个Object对象,用户使用时,需要对获取的结果进行转换类型 */ public Object getBean(String beanName) { return this.sigletons.get(beanName); }}?
?
?
?
3、在测试类中使用自定义的IoC容器:
public class Test { public static void main(String[] args) { //IOC容器实例化 WxyClassPathXMLApplicationContext ctx = new WxyClassPathXMLApplicationContext("beans.xml"); //获取业务bean PeopleServiceBean peopleService = (PeopleServiceBean) ctx.getBean("peopleService"); peopleService.save(); } }?
测试结果:
-----------------------------------------
--> the method is called save()!
-----------------------------------------