简单的IOC其实就是一个map,key是对象名字,value是对象的实例,Spring容器初始化的时候会将配置文件或注解信息转换成BeanDefinition对象存储在集合中,然后遍历集合通过反射实例化Bean,实例化后的Bean会放入到名为singletonObjects的Map中,当调用getBean的时候会从singletonObjects对象中取出对应的Bean实例。
一:定义一个BeanDefinition
package com.tiny.spring.beans.factory.config; public class BeanDefinition {private String id;private String className;public BeanDefinition() {}public BeanDefinition(String id, String className) {this.id = id;this.className = className;}public String getId() {return id;}public void setId(String id) {this.id = id;}public String getClassName() {return className;}public void setClassName(String className) {this.className = className;} }
二:读取配置文件并反射生成对象
package com.tiny.spring.context.support;import com.tiny.spring.beans.factory.config.BeanDefinition; import org.dom4j.Document; import org.dom4j.DocumentException; import org.dom4j.Element; import org.dom4j.io.SAXReader;import java.net.URL; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; public class ClassPathXmlApplicationContext {private List<BeanDefinition> beanDefinitions = new ArrayList<>();private Map<String, Object> singletons = new HashMap<>();public ClassPathXmlApplicationContext(String pathname) {this.readXml(pathname);this.instanceBeans();}private void readXml(String pathname) {SAXReader saxReader = new SAXReader();try {URL xmlPath = this.getClass().getClassLoader().getResource(pathname);Document document = saxReader.read(xmlPath);Element rootElement = document.getRootElement();// 对配置文件的每一个<bean>标签进行处理for (Element element : rootElement.elements()) {// 获取Bean的基本信息String beanId = element.attributeValue("id");String beanClassName = element.attributeValue("class");BeanDefinition beanDefinition = new BeanDefinition(beanId, beanClassName);// 将Bean的定义存放到BeanDefinition beanDefinitions.add(beanDefinition);}} catch (DocumentException e) {e.printStackTrace();}}/*** 利用反射创建Bean实例,并存储在singletons中*/private void instanceBeans() {for (BeanDefinition beanDefinition : beanDefinitions) {try {singletons.put(beanDefinition.getId(), Class.forName(beanDefinition.getClassName()).newInstance());} catch (InstantiationException | IllegalAccessException | ClassNotFoundException e) {e.printStackTrace();}}}/*** 对外提供的方法,让外部程序获取Bean实例* @param beanName* @return*/public Object getBean(String beanName) {return singletons.get(beanName);} }
三:结果测试
package com.tiny.spring.test;import com.tiny.spring.beans.BeansException; import com.tiny.spring.context.support.ClassPathXmlApplicationContext; import com.tiny.spring.test.service.AService;public class OriginalIoCContainerTest {public static void main(String[] args) throws BeansException {ClassPathXmlApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("beans.xml");AService aService = (AService) classPathXmlApplicationContext.getBean("aService");aService.sayHello();} }
