手动开发-简单的Spring基于XML配置的程序--源码解析

本文涉及的产品
云解析 DNS,旗舰版 1个月
全局流量管理 GTM,标准版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
简介: 手动开发-简单的Spring基于XML配置的程序--源码解析

本文带着大家写一个简单的Spring容器,通过读取beans.xml配置文件,获取第一个JavaBean:Monster的对象,并给对象赋值,放入到容器中,输出对象信息。

先回顾一下使用Spring时,我们是通过ClassPathXmlApplicationContext得到ioc容器,容器自动读取beans.xml配置文件,我们通过容器的getBean方法获取到对象,并输出该对象。

现在要做的就是:

  • 自己实现一个ioc容器,前提是自己实现一个属于自己的ClassPathXmlApplicationContext()
  • ClassPathXmlApplicationContext()中要提供一个getBean()方法。

思路分析@

这里其实重点分析ClassPathXmlApplicationContext()的具体实现过程:

  • 定义一个iocConcurrentHashMap,存放对象名id和对象的映射。
  • 创建一个构造器,将下面的操作都放在这个构造器里
  • 使用xml解析技术-dom4j技术,将beans.xml文件中的信息读取出来,并获取到节点信息的属性值
  • 使用反射创建对象
  • 将对象放入到ioc
  • 提供一个getBean方法

在通过 xml解析技术-dom4j技术,将beans.xml文件中的信息读取出来,并获取到节点信息的属性值时,需要先获取到beans.xml文件所在路径 。这里的路径是指 项目 编译后的文件所在路径,也就是target工作目录下的路径,我们的beans.xml文件是放在resource目录下的,经过编译后就会跑到target/classes目录下,所以在这里我们通过dom4j读取的目录应该是D:/Java/JavaProjects/spring-context-v1/target/classes/ ;完整的 文件工作路径应该是D:/Java/JavaProjects/spring-context-v1/target/classes/beans.xml ;

String path = this.getClass().getResource("/").getPath();
//        System.out.println("path="+path);
        SAXReader saxReader = new SAXReader();
        Document document = saxReader.read(new File(path + iocBeanXmlFile));

在获取到document文档对象以后,我们就拿到了beans.xml里的所有内容,这个时候,我们获取到根节点,再通过根节点获取到bean标签的第一个bean对象,bean标签内的属性极其属性值都能获取到。通过bean标签的class属性可以获取到全类路径,拿到类路径就可以通过反射创建对象,这个对象的类型就是你类路径的对象。

SAXReader saxReader = new SAXReader();
        Document document = saxReader.read(new File(path + iocBeanXmlFile));
        Element rootElement = document.getRootElement();
        Element bean = (Element) rootElement.elements("bean").get(0);
        String id = bean.attributeValue("id");
        String classFullPath = bean.attributeValue("class");
        System.out.println("id="+id);
        System.out.println("classFullPath="+classFullPath);
        List<Element> property = bean.elements("property");
        String monsterId = property.get(0).attributeValue("value");
        String name = property.get(1).attributeValue("value");
        System.out.println("monsterId="+monsterId);
        System.out.println("name="+name);

通过反射创建的对象才能和Monster对象有相似的结构,我们可以把beans.xml中取出来的bean对象的属性值注入到我们反射创建的对象中,再把这个对象加入到ioc集合中。

Class<?> aClass = Class.forName(classFullPath);
        Monster o = (Monster) aClass.newInstance();
        o.setId(Integer.valueOf(monsterId));
        o.setName(name);
        ioc.put(id,o);

最后提供一个getBean方法,给出 monsterId的时候,能从ioc容器中找到对应映射的Monster对象。

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

最后就实现了上图,我们只需要在xml文件中配置bean对象,再把xml文件的名字交给LingHuApplication容器进行初始化就可以得到一个ioc容器,ioc容器的本质就是一个ConcurrentHashMap。内部是通过dom4j去读取了bean对象的配置信息,通过这些信息如classFullPath反射创建对象,在往这个新对象中注入读取到bean对象的配置信息。这个新对象被我们放入到ConcurrentHashMap中了,我们通过getBean(String monsterId)方法去遍历ConcurrentHashMap找到新对象。

做这些事情的意义就在于,我们将配置工作和业务工作进行了分离,繁琐的对象管理工作一律通过配置文件来完成,降低了代码的耦合性,剥离了业务代码。所以Spring的容器思想的本质就是:ConcurrentHashMap+反射创建对象。

完整代码&:

LingHuApplication.java:

package com.linghu.spring.linghuapplication;
import com.linghu.spring.bean.Monster;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.springframework.context.annotation.ComponentScan;
import java.io.File;
import java.net.MalformedURLException;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
/**
 * @author 
 * @version 1.0
 *  * 1. 这个程序用于实现Spring的一个简单容器机制
 *  * 2. 后面我们还会详细的实现
 *  * 3. 这里我们实现如何将beans.xml文件进行解析,并生成对象,放入容器中
 *  * 4. 提供一个方法 getBean(id) 返回对应的对象
 *  * 5. 这里就是一个开胃小点心, 理解Spring容器的机制
 */
public class LingHuApplication {
    private ConcurrentHashMap<String, Object> ioc =
            new ConcurrentHashMap<>();
    public LingHuApplication(String iocBeanXmlFile) throws MalformedURLException, DocumentException, ClassNotFoundException, InstantiationException, IllegalAccessException {
        String path = this.getClass().getResource("/").getPath();
//        System.out.println("path="+path);
        //得到一个解析器
        SAXReader saxReader = new SAXReader();
        //老师的代码技巧->debug 看看document对象的属性
        //分析了document对象的底层结构
        Document document = saxReader.read(new File(path+iocBeanXmlFile));
        //1. 得到rootElement, 你是OOP
        Element rootElement = document.getRootElement();
        //2. 得到第一个bean-monster01
        Element bean = (Element) rootElement.elements("bean").get(0);
        //获取到第一个bean-monster01的相关属性
        String id = bean.attributeValue("id");
        String classFullPath = bean.attributeValue("class");
        List<Element> property = bean.elements("property");
        System.out.println("id="+id);
        System.out.println("classFullPath="+classFullPath);
        //获取bean对象中的property属性值-id和name
        String name = property.get(1).attributeValue("value");
        String monsterId = property.get(0).attributeValue("value");
        System.out.println("name="+name);
        System.out.println("id="+monsterId);
        //使用反射创建对象
        Class<?> aClass = Class.forName(classFullPath);
        //o对象就是monster对象
        Monster o = (Monster) aClass.newInstance();
//        System.out.println("o="+o);
        o.setId(Integer.valueOf(monsterId));
        o.setName(name);
        //将创建好的对象放入到ioc对象中
        ioc.put(id,o);
    }
    //提供一个getBean(id)返回对应的bean对象
    public Object getBean(String id){
        return ioc.get(id);
    }
}

Gitee:《手动开发-简单的Spring基于XML配置的程序》

目录
打赏
0
0
0
0
42
分享
相关文章
微服务——SpringBoot使用归纳——Spring Boot使用slf4j进行日志记录—— logback.xml 配置文件解析
本文解析了 `logback.xml` 配置文件的详细内容,包括日志输出格式、存储路径、控制台输出及日志级别等关键配置。通过定义 `LOG_PATTERN` 和 `FILE_PATH`,设置日志格式与存储路径;利用 `&lt;appender&gt;` 节点配置控制台和文件输出,支持日志滚动策略(如文件大小限制和保存时长);最后通过 `&lt;logger&gt;` 和 `&lt;root&gt;` 定义日志级别与输出方式。此配置适用于精细化管理日志输出,满足不同场景需求。
79 1
微服务——SpringBoot使用归纳——Spring Boot集成MyBatis——基于 xml 的整合
本教程介绍了基于XML的MyBatis整合方式。首先在`application.yml`中配置XML路径,如`classpath:mapper/*.xml`,然后创建`UserMapper.xml`文件定义SQL映射,包括`resultMap`和查询语句。通过设置`namespace`关联Mapper接口,实现如`getUserByName`的方法。Controller层调用Service完成测试,访问`/getUserByName/{name}`即可返回用户信息。为简化Mapper扫描,推荐在Spring Boot启动类用`@MapperScan`注解指定包路径避免逐个添加`@Mapper`
31 0
JS数组操作方法全景图,全网最全构建完整知识网络!js数组操作方法全集(实现筛选转换、随机排序洗牌算法、复杂数据处理统计等情景详解,附大量源码和易错点解析)
这些方法提供了对数组的全面操作,包括搜索、遍历、转换和聚合等。通过分为原地操作方法、非原地操作方法和其他方法便于您理解和记忆,并熟悉他们各自的使用方法与使用范围。详细的案例与进阶使用,方便您理解数组操作的底层原理。链式调用的几个案例,让您玩转数组操作。 只有锻炼思维才能可持续地解决问题,只有思维才是真正值得学习和分享的核心要素。如果这篇博客能给您带来一点帮助,麻烦您点个赞支持一下,还可以收藏起来以备不时之需,有疑问和错误欢迎在评论区指出~
分片上传技术全解析:原理、优势与应用(含简单实现源码)
分片上传通过将大文件分割成多个小的片段或块,然后并行或顺序地上传这些片段,从而提高上传效率和可靠性,特别适用于大文件的上传场景,尤其是在网络环境不佳时,分片上传能有效提高上传体验。 博客不应该只有代码和解决方案,重点应该在于给出解决方案的同时分享思维模式,只有思维才能可持续地解决问题,只有思维才是真正值得学习和分享的核心要素。如果这篇博客能给您带来一点帮助,麻烦您点个赞支持一下,还可以收藏起来以备不时之需,有疑问和错误欢迎在评论区指出~
讲解SSM的xml文件
本文详细介绍了SSM框架中的xml配置文件,包括springMVC.xml和applicationContext.xml,涉及组件扫描、数据源配置、事务管理、MyBatis集成以及Spring MVC的视图解析器配置。
135 1
Spring5入门到实战------7、IOC容器-Bean管理XML方式(外部属性文件)
这篇文章是Spring5框架的实战教程,主要介绍了如何在Spring的IOC容器中通过XML配置方式使用外部属性文件来管理Bean,特别是数据库连接池的配置。文章详细讲解了创建属性文件、引入属性文件到Spring配置、以及如何使用属性占位符来引用属性文件中的值。
Spring5入门到实战------7、IOC容器-Bean管理XML方式(外部属性文件)
Eclipse 创建 XML 文件
Eclipse 创建 XML 文件
79 2
|
5月前
|
maven项目的pom.xml文件常用标签使用介绍
第四届人文,智慧教育与服务管理国际学术会议(HWESM 2025) 2025 4th International Conference on Humanities, Wisdom Education and Service Management
471 8
|
6月前
|
java与XML文件的读写
java与XML文件的读写
58 3

热门文章

最新文章

推荐镜像

更多