• Spring容器的简单实现(IOC原理)


    引言:容器是什么?什么是容器?Spring容器又是啥东西?我给Spring容器一个对象名字,为啥能给我创建一个对象呢?

    一、容器是装东西的,就像你家的水缸,你吃饭的碗等等。

          java中能作为容器的有很多,例如Map,List,数组.....还有好多

    二、Spring 容器的核心就是一个Map集合(可能不是很准确,见谅!)

      Map<String, Object> 这个容器里根据key-value存放了好多键值对。假如你给一个String的key,就能获得相应的Object的对象,各位大佬,对Spring容器是不是有拨开云雾见太阳的感觉了?[/斜眼笑]

      Spring工厂的作用:帮助我们创建管理对象。
       <一>BeanFactory
        1、定义Map容器,key-类名、value-对象
        2、解析bean.xml文件
        3、根据name返回对象

     1 package com.demo.ioc.theory.factory;
     2 
     3 import java.util.Map;
     4 
     5 import com.demo.ioc.theory.util.ParseHelper;
     6 
     7 public class BeanFactory {
     8     //定义的Map<类名,对象>的容器
     9     private Map<String, Object> map;
    10     //无参构造器传的是bean.xml文件的路径
    11     public BeanFactory() {
    12         this("src/bean.xml");
    13     }
    14     //这个构造器调用方法解析xml文件,返回值就是  类名-对象 的关系
    15     public BeanFactory(String path) {
    16         try {
    17             map = ParseHelper.parseXml(path);
    18         } catch (Exception e) {
    19             e.printStackTrace();
    20         }
    21     }
    22     //根据类名获取对象的方法
    23     public Object getBean(String beanName) {
    24         return map.get(beanName);
    25     }
    26 }

                <二>解析bean.xml文件(dom4j解析)

           需要导入dom4j的相关jar包,下载地址  http://central.maven.org/maven2/dom4j/dom4j/1.6.1/dom4j-1.6.1.jar

            这个解析简单,直接上代码:

    package com.demo.ioc.theory.util;
    
    import java.io.File;
    import java.lang.reflect.Method;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    
    import org.dom4j.Document;
    import org.dom4j.Element;
    import org.dom4j.io.SAXReader;
    
    @SuppressWarnings("unchecked")
    public class ParseHelper {
        public static Map<String, Object> parseXml(String path) throws Exception {
            Map<String, Object> map = new HashMap<>();
            // 创建saxReader对象  
            SAXReader saxReader = new SAXReader();
            //通过read方法读取一个文件 转换成Document对象  
            Document document = saxReader.read(new File(path));
            //获取根节点元素对象
            Element rootElement = document.getRootElement();
            List<Element> elements = rootElement.elements();
            for(Element e:elements){
                
                String beanName = e.attributeValue("name");
                String className = e.attributeValue("class");
                
                Object o = Class.forName(className).newInstance();
                
                map.put(beanName,o);
                List<Element> elements2 = e.elements();
                for(Element e2:elements2){
                    //<property name="student" ref="stu"></property>
                    String propertyName = e2.attributeValue("name"); 
                    String refName = e2.attributeValue("ref");
                    
                    //调用当前类中的一个私有方法 通过参数student获得其对应的set方法名:setStudent
                    String methodName = getMethodName(propertyName);
                    //通过对象名字stu从map中获得其对应的对象
                    Object obj = map.get(refName);
                    //获得setStudent方法镜像
                    Method method = o.getClass().getMethod(methodName, new Class[]{obj.getClass()});
                    //反射调用该方法 相当于 t.setStudent(stu);
                    method.invoke(o, obj);
                }
            }
            return map;
        }
        //可以把字符串参数xxx转变为setXxx
        private static String getMethodName(String s) {
            s = s.substring(0,1).toUpperCase() + s.substring(1,s.length());
            return "set"+s;
        }
    }

              <三>配置文件bean.xml文件

    <?xml version="1.0" encoding="UTF-8"?>
    <beans>
        <bean name="student" class="com.demo.ioc.theory.bean.Student">
        </bean>
    </beans>

            <四>实体类,Student.java

    package com.demo.ioc.theory.bean;
    
    public class Student {
        private String name;
        private String age;
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        public String getAge() {
            return age;
        }
        public void setAge(String age) {
            this.age = age;
        }
    }

          <五>测试自己做的IOC容器

    package com.demo.ioc.theory;
    
    import com.demo.ioc.theory.bean.Student;
    import com.demo.ioc.theory.factory.BeanFactory;
    
    public class IocTest {
        public static void main(String[] args) {
            //创建工厂对象
            BeanFactory beanFactory = new BeanFactory();
            //通过工厂直接拿到Student对象,不用去 new Student();
            Student bean = (Student) beanFactory.getBean("student");
            //测试
            bean.setAge("20");
            System.out.println(bean.getAge());
        }
    }

    到此,一个简单的Spring Ioc容器就实现了,这个容器可以根据配置文件配置的信息获取到对应的对象。不需要再去new对象了。当然,这只是最简单的,你也可以再去深入....

    下面是我的demo的项目结构,瞧一瞧哦

  • 相关阅读:
    error C2065: 'IDD_DIALOG1' : undeclared identifier
    MySQL API函数
    MFC连接MySQL C API方法
    MFC连接MySQL
    MFC连接MySQL数据库方法
    error C4430: error 2141
    GetLastError
    char与CString相互转换
    处理图片(获取图片详细信息)大小 格式
    RGB颜色值 十六进制颜色码 转换
  • 原文地址:https://www.cnblogs.com/baijinqiang/p/9468929.html
Copyright © 2020-2023  润新知