标签:
先回顾一下前文。前文说过,Spring的容器,通过读取配置文件,利用反射机制,实现了对象的创建,这是核心。
模拟步骤
目录结构
<?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>
package spring.container;
/**
* @author Administrator
*
*/
public interface BeanFactory {
public Object getBean(String id);
}
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);
}
}
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;
}
}
定义了一个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 + "说中文。");
}
}
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出来的,而是通过配置文件解析,由容器创建的。
标签:
原文地址:http://blog.csdn.net/qq_33938256/article/details/51340097