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;
- }
- }
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);
- }
- }
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();
- }
- }
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()!
-----------------------------------------