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出来的,而是通过配置文件解析,由容器创建的。
相关文章推荐
- 关于开发springmvc和mybatis的环境搭建
- 配置java编译环境
- Java开发中的23种设计模式详解
- MyEclipse配置Maven
- Java设计模式
- 关于java.split问题
- java多线程
- Java线程详解
- Spring记录之Spring的基本概念
- 第十四章 springboot + profile(不同环境读取不同配置)
- eclipse最常用的10种快捷键组合
- Eclipse Che开发Spring Web应用(入门) (二)
- springMVC知识点学习笔记
- java学习总结(16.05.07) jdk的安装与环境变量的配置
- java学习之final关键字
- 设计模式--观察者模式初探和java Observable模式
- 04 Java API
- Java集合框架
- java多线程学习-java.util.concurrent详解(二)Semaphore/FutureTask/Exchanger
- 如何学好java?