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

news2024/10/9 6:21:00

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

文章目录

  • 手动开发-简单的Spring基于XML配置的程序
    • 思路分析@
    • 完整代码&:

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

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

img

现在要做的就是:

  • 自己实现一个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集合中。

img

        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);
    }

img

最后就实现了上图,我们只需要在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配置的程序》

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/994314.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

光源控制器光源亮度调节操作说明

光源控制器光源亮度调节操作说明 光源亮度的调节在许多应用中都扮演着至关重要的角色&#xff0c;不仅影响图像质量&#xff0c;还能改善工作环境。下面是关于光源控制器光源亮度调节的详细操作步骤&#xff0c;帮助您轻松实现亮度的合适调整。 步骤一&#xff1a;登录系统 …

MySQL——常见问题

NULL和空值的区别 1、空值不占空间&#xff0c;NULL值占空间。当字段不为NULL时&#xff0c;也可以插入空值。 2、当使用 IS NOT NULL 或者 IS NULL 时&#xff0c;只能查出字段中没有不为NULL的或者为 NULL 的&#xff0c;不能查出空值。 3、判断NULL 用IS NULL 或者 is no…

Bootstrap与响应式图片设计相关的类

01-图像随父元素的同步缩放 可以利用类 .img-fluid 实现图像随父元素同步缩放。 示例代码如下&#xff1a; <!DOCTYPE html> <html> <head><meta charset"UTF-8"><title>图像的同步缩放</title><meta name"viewport&…

C/C++标准输入输出函数最全解析(含C/C++的输出控制符)

C/C标准输入输出函数最全解析&#xff08;含C/C的输出控制符&#xff09; 一、标准输入流1、C 标准输入1.1 标准输入流及对缓冲区的理解1.2 scanf()1.2.1 scanf()简介1.2.2 ANSI C中scanf()的转换说明1.2. 3 scanf()转换说明中的修饰符 1.3 gets() - 不建议1.4 fgets()1.5 fget…

【笔记】大模型时代下做科研的四个思路 - 论文精读·52

视频地址&#xff1a;大模型时代下做科研的四个思路 相关大模型 CV: ViT(22B) , ViT-G(2B) from google 多模态&#xff1a;ViT-E(4B) from google NLP&#xff1a;LLaMA(70B,130B,330B,651B) from Meta 提问&#xff1a;在模型越来越大的时代背景下&#xff0c;如何利用有限…

【接口测试】微信小程序接口自动化的实现方案

背景 前几天看到有人问微信小程序怎么进行接口自动化&#xff0c;所以想把自己如何进行微信小程序接口自动化的方法分享下。 https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/login.html这是微信小程序的登陆流程&#xff0c;小程序登陆需要在小程序…

un-app-手机号授权登录-授权框弹不出情况

前言 手机号授权是获取用户信息api停用之后&#xff0c;经常使用的api。但是此api也是有很多坑 手机号授权会出现调用不起来的情况&#xff0c;这是因为小程序后台没有进行微信认证导致的 手机号授权调用不起来-没有微信认证 来到小程序后台-设置-基本设置-下拉找到微信认证…

【ModelSim】查看波形图(Wave)和数据流图(DataFlow),以4-bit计数器为例

▚ 00 预备条件 &#x1f4e2; 本项目包括两个Verilog文件&#xff1a;测试文件counter.v和激励文件testbench.v&#xff1b;可从此处点击HERE获取。 &#x1f3ae; Windows10系统 &#x1f52e; ModelSim SE-64 2020.4 ▚ 01 启动ModelSim 有两种方式可以打开ModelSim&a…

vue下载与部分指令详解

目录 vue 下载地址 前端框架 MVC与MVVM框架 Vue使用 Vue.js指令 ​编辑 v-if v-else v-show v-on v-model&#xff08;表单绑定&#xff09; v-bind v-for v-text v-model 指令扩展 vue 下载地址 官方入门&#xff1a;https://cn.vuejs.org/ API 文档&#…

如何给网站或者后端服务免费且快速的进行配置HTTPS,配置ssl证书

前言 现在部署的网站用的大多都是https协议的,还有的平台你要是想发布自己的网站就必须得是https的协议,如果不使用ssl的话,那就不让你使用.就比如微信,支付宝等的产品,不用的话就不让你使用他们的平台.不过还好很多服务厂商都提供了免费ssl证书可以进行配置 今天的情况比较特殊…

常用电子元器件基础知识

目录 一、电阻 二、电容 三、电感 四、保险丝 五、二极管 一、电阻 概念&#xff1a;顾名思义&#xff0c;就是增加电流通过的阻力的。 就像是在水渠中放入东西&#xff0c;能阻止水的顺利通过也是一个道理。 基于电阻的电气特性&#xff0c;电阻在电路中主要有以下四个…

Solidity 小白教程:11. 构造函数和修饰器

Solidity 小白教程&#xff1a;11. 构造函数和修饰器 这一讲&#xff0c;我们将用合约权限控制&#xff08;Ownable&#xff09;的例子介绍solidity语言中构造函数&#xff08;constructor&#xff09;和独有的修饰器&#xff08;modifier&#xff09;。 构造函数 构造函数&…

栈与队列(JAVA)

单调栈&#xff1a; 下一个更大元素。 题目意思如图所示&#xff1a; 单调栈图解&#xff1a; class Solution {public int[] nextGreaterElement(int[] nums1, int[] nums2) {Stack<Integer>stacknew Stack<>();int res[]new int[nums2.length];int ans[]new int…

为什么要使用Token

传统的session认证 我们知道&#xff0c;http协议是一种无状态的协议&#xff0c;这就意味着当用户向我们的应用提供了用户名和密码进行用户认证&#xff0c;那么在下一次登录的时候&#xff0c;用户还要再进行验证&#xff0c;因为根据http协议&#xff0c;浏览器并不知道是谁…

Shipping mode --为省电而生

关于shipping mode 相信很多做消费类电子产品的硬件工程师对这对英文耳熟能详。日常家用的手机&#xff0c;电脑&#xff0c;电子手表都用到了这项技术。 shipping mode可译为运输模式&#xff0c;又或者船运模式&#xff0c;其技术的实现主要依靠于电子产品中的充电管理芯片。…

Java自学网站推荐--全网最靠谱

原文网址&#xff1a;Java自学网站推荐--全网最靠谱_IT利刃出鞘的博客-CSDN博客 简介 网上有各种Java学习网站&#xff0c;本文推荐的这个Java网站全网最靠谱&#xff0c;质量远超其他所有网站。 这个网站是&#xff1a;自学精灵&#xff0c;这是全网最强的Java学习网站&…

SpringBootWeb请求-响应

HTTP请求 前后端分离 在这种模式下&#xff0c;前端技术人员基于"接口文档"&#xff0c;开发前端程序&#xff1b;后端技术人员也基于"接口文档"&#xff0c;开发后端程序。 由于前后端分离&#xff0c;对我们后端技术人员来讲&#xff0c;在开发过程中&a…

机器学习算法详解2:线性回归

机器学习算法详解2&#xff1a;线性回归 前言 ​ 本系列主要对机器学习上算法的原理进行解读&#xff0c;给大家分享一下我的观点和总结。 本篇前言 ​ 本篇对线性回归的算法原理进行解读。 目录结构 文章目录 机器学习算法详解2&#xff1a;线性回归1. 引子2. 原理3. 特点4. 问…

如何使用SQL SERVER的OpenQuery

如何使用SQL SERVER的OpenQuery 一、OpenQuery使用说明二、 OpenQuery语法2.1 参数说明2.2注解 三、示例3.1 执行 SELECT 传递查询3.2 执行 UPDATE 传递查询3.3 执行 INSERT传递查询3.4 执行 DELETE 传递查询 一、OpenQuery使用说明 在指定的链接服务器上执行指定的传递查询。 …

领域驱动设计:DDD 关键概念

文章目录 领域和子域核心域、通用域和支撑域通用语言限界上下文实体值对象聚合聚合根设计聚合 DDD 的知识体系提出了很多的名词&#xff0c;像&#xff1a;领域、子域、核心域、通用域、支撑域、限界上下文、聚合、聚合根、实体、值对象等等&#xff0c;非常多。 领域和子域 …