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的项目结构,瞧一瞧哦

原文地址:https://www.cnblogs.com/baijinqiang/p/9468929.html