zoukankan      html  css  js  c++  java
  • 手动实现Spring中的IOC容器

    注意:这就是一个用于学习理解Spring中IOC容器的简单例子!!!!

    1、IOC容器实现的过程:

    • 加载XML的配置文件,并且遍历文件中的标签
    • 获取配置文件中单个Bean的ID和Class属性,然后根据Class文件加载对应的类,并且创建Bean的实例对象
    • 获取属性标签中的属性值,填充到Bean的中
    • 将设置好的Bean注册到IOC容器中

    2、代码展示:

    package com.baozi.Test;
    
    import org.w3c.dom.Document;
    import org.w3c.dom.Element;
    import org.w3c.dom.Node;
    import org.w3c.dom.NodeList;
    
    import javax.xml.parsers.DocumentBuilder;
    import javax.xml.parsers.DocumentBuilderFactory;
    import java.io.FileInputStream;
    import java.io.InputStream;
    import java.lang.reflect.Field;
    import java.util.HashMap;
    import java.util.Map;
    
    /**
     * @author BaoZi
     * @create 2019-07-19-8:54
     */
    public class SimpleIOC {
        private Map<String, Object> beanMap = new HashMap<>();
    
        public SimpleIOC(String location) throws Exception {
            loadBeans(location);
        }
    
        public Object getBean(String name) {
            Object bean = beanMap.get(name);
            if (bean == null) {
                throw new IllegalArgumentException("there is no bean with name " + name);
            }
    
            return bean;
        }
    
        private void loadBeans(String location) throws Exception {
            // 加载 xml 配置文件
            //把要解析的 XML 文档转化为输入流对象,以便 DOM 解析器解析它
            InputStream inputStream = new FileInputStream(location);
            /**
             * javax.xml.parsers 包中的DocumentBuilderFactory用于创建DOM模式的解析器对象 ,
             * DocumentBuilderFactory是一个抽象工厂类,它不能直接实例化,但该类提供了一个newInstance方法 ,
             * 这个方法会根据本地平台默认安装的解析器,自动创建一个工厂的对象并返回。
             */
            //调用 DocumentBuilderFactory.newInstance() 方法得到创建 DOM 解析器的工厂。
            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
            //调用工厂对象的 newDocumentBuilder方法得到 DOM 解析器对象。
            DocumentBuilder docBuilder = factory.newDocumentBuilder();
            //调用 DOM 解析器对象的 parse() 方法解析 XML 文档,得到代表整个文档的 Document 对象,
            // 进行可以利用DOM特性对整个XML文档进行操作了。
            Document doc = docBuilder.parse(inputStream);
            //得到 XML 文档的根节点
            Element root = doc.getDocumentElement();
            //得到节点的子节点
            NodeList nodes = root.getChildNodes();
    
            // 遍历 <bean> 标签
            for (int i = 0; i < nodes.getLength(); i++) {
                Node node = nodes.item(i);
                if (node instanceof Element) {
                    Element ele = (Element) node;
                    String id = ele.getAttribute("id");
                    String className = ele.getAttribute("class");
    
                    // 加载 beanClass
                    Class beanClass = null;
                    try {
                        beanClass = Class.forName(className);
                    } catch (ClassNotFoundException e) {
                        e.printStackTrace();
                        return;
                    }
    
                    // 创建 bean
                    Object bean = beanClass.newInstance();
    
                    // 遍历 <property> 标签
                    //使用Document对象的getElementsByTagName()方 法,我们可以得到一个NodeList对象,
                    // 一个Node对象代表了一个XML文档中的一个标签元素,而NodeList对象,观其名而知其意,
                    // 所代表的是一个Node对象的列表:
                    NodeList propertyNodes = ele.getElementsByTagName("property");
                    for (int j = 0; j < propertyNodes.getLength(); j++) {
                        Node propertyNode = propertyNodes.item(j);
                        if (propertyNode instanceof Element) {
                            Element propertyElement = (Element) propertyNode;
                            String name = propertyElement.getAttribute("name");
                            String value = propertyElement.getAttribute("value");
    
                            // 利用反射将 bean 相关字段访问权限设为可访问
                            Field declaredField = bean.getClass().getDeclaredField(name);
                            declaredField.setAccessible(true);
    
                            if (value != null && value.length() > 0) {
                                // 将属性值填充到相关字段中
                                declaredField.set(bean, value);
                            } else {
                                //这里是Bean对象属性中循环引用问题(先不做处理)
                                String ref = propertyElement.getAttribute("ref");
                                if (ref == null || ref.length() == 0) {
                                    throw new IllegalArgumentException("ref config error");
                                }
    
                                // 将引用填充到相关字段中
                                declaredField.set(bean, getBean(ref));
                            }
    
                            // 将 bean 注册到 bean 容器中
                            registerBean(id, bean);
                        }
                    }
                }
            }
        }
        //这里模仿Bean对象注入IOC容器中的过程
        private void registerBean(String id, Object bean) {
            beanMap.put(id, bean);
        }
    }
    

      

    3、测试实例:

    Bean的实力对应的类:

    public class Car {
        private String name;
        private String length;
        private String width;
        private String height;
        private Wheel wheel;
      //..........................
    }
    
    public class Wheel {
        private String brand;
        private String specification ;
        
        // ............................
    }
    

      测试用的XML文件:

    <beans>
        <bean id="wheel" class="com.baozi.Wheel">
            <property name="brand" value="Michelin" />
            <property name="specification" value="265/60 R18" />
        </bean>
    
        <bean id="car" class="com.baozi.Car">
            <property name="name" value="Mercedes Benz G 500"/>
            <property name="length" value="4717mm"/>
            <property name="width" value="1855mm"/>
            <property name="height" value="1949mm"/>
            <property name="wheel" ref="wheel"/>
        </bean>
    </beans>
    

      测试类:

    public class SimpleIOCTest {
        @Test
        public void getBean() throws Exception {
            String location = SimpleIOC.class.getClassLoader().getResource("spring-test.xml").getFile();
            SimpleIOC bf = new SimpleIOC(location);
            Wheel wheel = (Wheel) bf.getBean("wheel");
            System.out.println(wheel);
            Car car = (Car) bf.getBean("car");
            System.out.println(car);
        }
    }
    

      

  • 相关阅读:
    react 性能优化
    JS获取当前网页大小以及屏幕分辨率等
    创建对象的6种方式总结
    版本号规则
    JS事件模型
    浅谈虚拟DOM
    浏览器的回流与重绘
    JavaScript预编译
    canvas学习笔记
    java、tomcat安装
  • 原文地址:https://www.cnblogs.com/BaoZiY/p/11375242.html
Copyright © 2011-2022 走看看