Spring的学习(上)

1、Spring的Beans.xml

 一个beans.xml示例:




    
    
    
        
        
        
    

获取Bean对象的过程:

    @Test
    public void getMonster() {

        // 1. 创建容器 ApplicationContext 该容器和容器配置文件关联
        ApplicationContext ioc = new ClassPathXmlApplicationContext("beans.xml");

        // 2. 通过getBean获取对应的对象
        // 默认返回Object 运行类型肯定是Monster
        Object monster01 = ioc.getBean("monster01");

        // 3. 输出
        System.out.println(monster01); // Monster{monsterId=100, name='牛魔王', skill='芭蕉扇'}
        System.out.println(monster01.getClass()); // 运行类型 class com.hspedu.spring.bean.Monster

        // 4. 也可以在获取的时候直接指定Class类型
        Monster monster = ioc.getBean("monster01", Monster.class);
        System.out.println(monster); // Monster{monsterId=100, name='牛魔王', skill='芭蕉扇'}

    }

getBean的运行流程:

Spring的学习(上)_第1张图片

获取容器中的所有BeanID:

Spring的学习(上)_第2张图片

1.1、自定义一个容器HspApplicationContext

自己写一个简单的Spring容器,通过读取beans.xml, 获取第一个JavaBean:Monster对象,并给该对象赋值,放入到容器中,输出该对象的信息

Spring的学习(上)_第3张图片

流程:

  • 先解析beans.xml
  • 得到第一个bean的信息,beanID、Class、属性、属性值
  • 使用反射生成对象,并赋值
  • 将创建好的bean对象,放入到singletonObjects集合中
  • 提供getBean(id)可以返回对应的bean对象

Spring的学习(上)_第4张图片

bean.xml:




    
    
    
        
        
        
    

    
        
        
        
    

Java代码:

package com.hspedu.spring.hspapplicationcontext;

import com.hspedu.spring.bean.Monster;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import java.io.File;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @Author: lihaojie
 * @Description:
 * 1、这个程序用于实现Spring的一个简单容器机制
 * 2、后面还会详细的实现
 * 3、这里我们实现如何将beans.xml文件进行解析并生成对应对象放入到容器在中
 * 4、提供一个方法 getBean(String id) 返回对应的对象
 * @DateTime: 2024/1/29 15:14
 **/
public class HspApplicationContext {

    private ConcurrentHashMap singletonObjects = new ConcurrentHashMap<>();

    // 构造器接收一个容器的配置文件 比如beans.xml 该文件默认在src下
    public HspApplicationContext(String iocBeanXmlPath) throws Exception {
        // 1、得到类加载路径
        String path = this.getClass().getResource("/").getPath();
        // 2、使用dom4j读取 创建saxReader
        SAXReader saxReader = new SAXReader();
        // 3、得到文档对象Document
        Document document = saxReader.read(new File(path + iocBeanXmlPath));
        // 4、得到rootDocument
        Element rootElement = document.getRootElement();
        // 5、得到第一个bean
        Element bean = (Element) rootElement.elements("bean").get(0);
        // 6、把id class 属性 都拿出来
        String id = bean.attributeValue("id");
        String classFullPath = bean.attributeValue("class");
        List property = bean.elements("property");
        // 直接获取
        Map kvs = new HashMap<>();
        for (Element element : property) {
            String name = element.attributeValue("name");
            String value = element.attributeValue("value");
            kvs.put(name, value);
        }
        // 7、使用反射创建对象
        Class aClass = Class.forName(classFullPath);
        // 这里的o对象就是Monster对象
        Monster monster = (Monster)aClass.newInstance();
        // 用反射来赋值
        Field[] declaredFields = aClass.getDeclaredFields();
        for (Field declaredField : declaredFields) {
            if (kvs.containsKey(declaredField.getName())) {
                declaredField.setAccessible(true);
                declaredField.set(monster, kvs.get(declaredField.getName()));
            }
        }
        // 8、放进容器
        singletonObjects.put(id, monster);
    }

    public Object getBean(String id) {
        return singletonObjects.get(id);
    }

}

1.2、Spring原生容器结构整理

Spring的学习(上)_第5张图片

思考:如果beans.xml中不去配id,会不会报错呢?

答案是不会,会正常运行,系统会默认分配ID,分配ID的规则:

全类名#0,全类名#1 这样的规则来分配ID

可以通过Debug的方式查看:

Spring的学习(上)_第6张图片

1.3、Spring配置Bean的基本介绍

Bean的管理分为两方面:

  • 创建bean对象
  • 给bean注入属性

1.4、从容器中获取bean的方式

1.4.1、按照类型去获取

案例:通过Spring的ioc容器,获取一个bean对象,获取bean的方式要求按照类型获取

Spring的学习(上)_第7张图片

Spring的学习(上)_第8张图片

但是,如果同类型的bean定义了两个,就会报错,看下面的例子:

Spring的学习(上)_第9张图片

Spring的学习(上)_第10张图片

这种使用Type赋值的场景有:

  • XXXAction/Servlet/Controller/XXXService 在一个线程中只需要一个对象实例的情况
  • 在容器配置文件中(比如beans.xml)中给属性赋值,底层是通过setter方法完成的,这也是为什么我们需要提供setter方法原因,没有setter运行会报错的

Spring的学习(上)_第11张图片

你可能感兴趣的:(spring,学习,java)