base - spring ioc原理-读取xml文件创建单例对象的简化实现

79 阅读1分钟

世界上并没有完美的程序,但是我们并不因此而沮丧,因为写程序就是一个不断追求完美的过程。

  1. 首先引入dom4j的依赖
<dependency>
    <groupId>dom4j</groupId>
     <artifactId>dom4j</artifactId>
     <version>1.6.1</version>
 </dependency>
  1. 然后创建spring的xml配置文件applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="helloService" name="helloService" class="com.test.demo.ioc.HelloService">

    </bean>
</beans>
  1. 最后实现配置文件的读取与实例的创建
    首先创建一个HelloService实例
package com.test.demo.ioc;
public class HelloService {
}

然后创建ioc容器

package com.test.demo.ioc;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import java.io.InputStream;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class HouApplicationContext {

    /**
     * map 用来存储唯一实例
     */
    private Map<String, Object> singleObjects = new ConcurrentHashMap<>(16);

    private String xmlPath;
    public HouApplicationContext(String xmlPath){
        this.xmlPath = xmlPath;
    }

    /**
     * 获取Bean
     * @param id
     * @return
     * @throws IllegalAccessException
     * @throws InstantiationException
     * @throws ClassNotFoundException
     * @throws DocumentException
     */
    public Object getBean(String id) throws IllegalAccessException, InstantiationException, ClassNotFoundException, DocumentException {
        if(!singleObjects.containsKey(id)){
            String className = readXml(id);
            Object o = newInstance(className);
            singleObjects.put(id, o);
        }
        return singleObjects.get(id);
    }

    /**
     * 通过反射创建实例
     * @param className
     * @return
     * @throws ClassNotFoundException
     * @throws IllegalAccessException
     * @throws InstantiationException
     */
    public Object newInstance(String className) throws ClassNotFoundException, IllegalAccessException, InstantiationException {
        return Class.forName(className).newInstance();
    }

    /**
     * 读取xml配置文件
     * @param id
     * @return
     * @throws DocumentException
     */
    public String readXml(String id) throws DocumentException {
        SAXReader reader = new SAXReader();
        Document dom = reader.read(getStream());
        List<Element> elements = dom.getRootElement().elements();
        String className = getElement(elements, id);
        return className;
    }

    /**
     * 获取className
     * @param elements
     * @param id
     * @return
     */
    public String getElement(List<Element> elements, String id){
        if(null == elements) {
            return null;
        }
        if(null == id){
            return null;
        }
        for(Element element: elements){
            String xmlId = element.attributeValue("id");
            if(id.equals(xmlId)){
                String className = element.attributeValue("class");
                return className;
            }
        }
        return null;
    }

    /**
     * 获取xml文件的输入流
     * @return
     */
    public InputStream getStream(){
        return this.getClass().getClassLoader().getResourceAsStream(xmlPath);
    }

    /**
     * 测试
     * @param args
     * @throws ClassNotFoundException
     * @throws InstantiationException
     * @throws DocumentException
     * @throws IllegalAccessException
     */
    public static void main(String[] args) throws ClassNotFoundException, InstantiationException, DocumentException, IllegalAccessException {
        HouApplicationContext context = new HouApplicationContext("applicationContext.xml");
        Object o = context.getBean("helloService");
        System.out.println(o);
    }
}

输出结果

com.test.demo.ioc.HelloService@7fac631b

在这里插入图片描述