Spring的学习(上)

1、Spring的Beans.xml

 一个beans.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">

    <!--配置一个Monster对象-->
    <!--
        1. 配置monster对象/javaBean
        2. 在beans中可以配置多个bean
        3. bean表示就是一个java对象
        4. class属性是用来指定类的全路径(因为底层是使用反射创建对象)
        5. id属性表示该java对象在Spring容器中的ID,通过ID可以获取到该对象
        6. <property name="monsterId" value="100"/> 用于给该对象的属性赋值
    -->
    <bean class="com.hspedu.spring.bean.Monster" id="monster01">
        <property name="monsterId" value="100"/>
        <property name="name" value="牛魔王"/>
        <property name="skill" value="芭蕉扇"/>
    </bean>

</beans>

获取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的运行流程:

获取容器中的所有BeanID:

1.1、自定义一个容器HspApplicationContext

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

流程:

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

bean.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">

    <!--配置一个Monster对象-->
    <!--
        1. 配置monster对象/javaBean
        2. 在beans中可以配置多个bean
        3. bean表示就是一个java对象
        4. class属性是用来指定类的全路径(因为底层是使用反射创建对象)
        5. id属性表示该java对象在Spring容器中的ID,通过ID可以获取到该对象
        6. <property name="monsterId" value="100"/> 用于给该对象的属性赋值
    -->
    <bean class="com.hspedu.spring.bean.Monster" id="monster01">
        <property name="monsterId" value="100"/>
        <property name="name" value="牛魔王"/>
        <property name="skill" value="芭蕉扇"/>
    </bean>

    <bean class="com.hspedu.spring.bean.Monster" id="monster02">
        <property name="monsterId" value="1001"/>
        <property name="name" value="牛魔王1"/>
        <property name="skill" value="芭蕉扇1"/>
    </bean>

</beans>

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<String, Object> 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<Element> property = bean.elements("property");
        // 直接获取
        Map<String, String> 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原生容器结构整理

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

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

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

可以通过Debug的方式查看:

1.3、Spring配置Bean的基本介绍

Bean的管理分为两方面:

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

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

1.4.1、按照类型去获取

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

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

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

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

相关推荐

  1. Spring MVC学习之——传文件

    2024-02-11 17:08:02       68 阅读
  2. 学习Spring,总停留在框架使用,该怎么办?

    2024-02-11 17:08:02       64 阅读
  3. C++学习string了解

    2024-02-11 17:08:02       43 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-02-11 17:08:02       98 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-02-11 17:08:02       106 阅读
  3. 在Django里面运行非项目文件

    2024-02-11 17:08:02       87 阅读
  4. Python语言-面向对象

    2024-02-11 17:08:02       96 阅读

热门阅读

  1. django中自定义视图样式

    2024-02-11 17:08:02       52 阅读
  2. 计算机网络相关题目及答案(第七章)

    2024-02-11 17:08:02       49 阅读
  3. Shell - 学习笔记 - 2.10 - Shell字符串截取

    2024-02-11 17:08:02       52 阅读
  4. MySQL进阶查询篇(7)-触发器的创建和使用

    2024-02-11 17:08:02       56 阅读
  5. 【Rust日报】2024-02-10 扩展 Rust Effect 系统

    2024-02-11 17:08:02       49 阅读
  6. 计算机视觉主要知识点

    2024-02-11 17:08:02       47 阅读
  7. P6359 [CEOI2018] Cloud computing 题解

    2024-02-11 17:08:02       46 阅读
  8. 笔趣阁小说批量爬取脚本代码

    2024-02-11 17:08:02       53 阅读