您的位置:首页 > 编程语言 > Java开发

Spring记录之模拟IoC(一)

2016-05-07 21:19 399 查看

模拟Spring IoC容器

先回顾一下前文。前文说过,Spring的容器,通过读取配置文件,利用反射机制,实现了对象的创建,这是核心。

模拟步骤

1.准备一个xml文件,配置好对象的关系

2.根据配置文件初始化容器

3.容器根据配置文件创建对象

目录结构



1.bean.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans>
<bean id="chinese" class="spring.beans.Chinese"></bean>

<bean id="english" class="spring.beans.English"></bean>
</beans>


2.准备容器

一个定义容器标准的接口

package spring.container;

/**
* @author Administrator
*
*/
public interface BeanFactory {

public Object getBean(String id);
}


3. 两种解析xml方法

Spring容器初始化的同时,会解析xml配置文件,所以在容器的构造方法里解析xml文件.

package spring.container;

import java.util.HashMap;
import java.util.Map;
import spring.parser.ConfigParser;

/**
* @author Administrator
*
*/
public class DomClassPathXMLApplicationContext implements BeanFactory {

private Map<String, Object> beans = new HashMap<String, Object>();

//parse xml file instantly this class is initializing
public DomClassPathXMLApplicationContext(String path) {
beans = ConfigParser.domParser(path);
}

@Override
public Object getBean(String id) {
return beans.get(id);
}
}


package spring.container;

import java.util.HashMap;
import java.util.Map;

import spring.parser.ConfigParser;

/**
* @author Administrator
*
*/
public class Dom4jClassPathXmlApplicationContext implements BeanFactory{

private Map<String, Object> beans = new HashMap<String, Object>();

//parse xml file instantly this class is initializing
public Dom4jClassPathXmlApplicationContext(String path) {
beans = ConfigParser.dom4jParser(path);
}

@Override
public Object getBean(String id) {
return beans.get(id);
}

}


解析xml配置文件的核心方法(1.0)

public class ConfigParser {

private static Map<String, Object> beans = new HashMap<String, Object>();

/**
* dom parse xml file
* @param path
* @return
*/
public static Map<String, Object> domParser(String path) {
org.w3c.dom.Document document = null;
try {

DocumentBuilderFactory factory = DocumentBuilderFactory
.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
document = builder.parse(DomClassPathXMLApplicationContext.class
.getResourceAsStream(path));

} catch (SAXException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
throw new RuntimeException(
"please check your configuration file. Make sure it is correct.");
} catch (ParserConfigurationException e) {
e.printStackTrace();
}

// 获取所有<bean>节点
NodeList beanList = document.getElementsByTagName("bean");

for (int i = 0; i < beanList.getLength(); i++) {

Node node = beanList.item(i);
NamedNodeMap namedNodeMap = node.getAttributes();
// dom解析属性是倒着来的,先class,再id,<bean id="" class=""></bean>
String clazz = namedNodeMap.item(0).getNodeValue();
String id = namedNodeMap.item(1).getNodeValue();
Object object;
try {

object = Class.forName(clazz).newInstance();
beans.put(id, object);

} catch (InstantiationException | IllegalAccessException
| ClassNotFoundException e) {
e.printStackTrace();
}

}
return beans;
}

/**
* dom4j parse xml file
* @param path
* @return
*/
public static Map<String, Object> dom4jParser(String path) {

// 1.parse xml configuration

SAXReader reader = new SAXReader();
org.dom4j.Document document = null;
try {
document = reader.read(Dom4jClassPathXmlApplicationContext.class
.getResourceAsStream(path));
} catch (DocumentException e) {
e.printStackTrace();
throw new RuntimeException(
"please check your configuration file. Make sure it is correct.");
}
// 2. define xPath to fetch all <bean>
String xpath = "//bean";
List<Element> list = document.selectNodes(xpath);

if (list.size() > 0) {
for (Element beanEle : list) {

String id = beanEle.attributeValue("id");
String clazz = beanEle.attributeValue("class");

try {
// use reflection to generate object
Object object = Class.forName(clazz).newInstance();
// put id and obj into a map
beans.put(id, object);

} catch (InstantiationException | IllegalAccessException
| ClassNotFoundException e) {
e.printStackTrace();
throw new RuntimeException(
"please check your configuration file." + id
+ "not found!");
} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
return beans;
}
}


4. 测试用的bean类

定义了一个Human接口

public interface Human {
public void speak();
}
.......
public class English implements Human{
private String name = "British";

@Override
public void speak() {
System.out.println(name + " speaks in English.");
}
}

......

public class Chinese implements Human{

private String name = "中国人";

@Override
public void speak() {
System.out.println(name + "说中文。");
}

}


5. 测试

public class ContainerTest {

@Test
public void testContainer(){
Dom4jClassPathXmlApplicationContext context = new Dom4jClassPathXmlApplicationContext("/bean.xml");
//      DomClassPathXMLApplicationContext context = new DomClassPathXMLApplicationContext("/bean.xml");
Chinese chinese = (Chinese) context.getBean("chinese");
English english = (English)context.getBean("english");
chinese.speak();
english.speak();

}
}


结果如下



至此,一个简单的Spring IoC模拟1.0就实现完毕了,对象创建不是new出来的,而是通过配置文件解析,由容器创建的。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: