Spring 如何管理 bean

2023-10-30

本文转载自:https://blog.csdn.net/l18848956739/article/details/80917853

常常听老师说容器,容器是什么?Spring 中是如何体现的?一直有疑惑,这两天看了一下Spring 管理 bean 的 Demo,对于 Spring 中的容器有了简单的认识。

本文只是对 bean 的一个超级简单的理解,实际 Spring 中的 bean 复杂多了

我们知道,容器是一个空间的概念,一般理解为可盛放物体的地方。在 Spring 容器通常理解为 BeanFactory 或者 ApplicationContext。我们知道 Spring 的 IoC 容器能够帮我们创建对象,对象交给 Spring 管理之后我们就不用手动去 new 对象。


BeanFactory 与 ApplicationContext 的区别是什么?

  • BeanFactory 采用了工厂设计模式,负责读取 bean 配置文档,管理 bean 的加载,实例化,维护 bean 之间的依赖关系,负责 bean 的声明周期
  • ApplicationContext 除了提供上述 BeanFactory 所能提供的功能之外,还提供了更完整的框架功能:国际化支持、AOP、事务等
  • BeanFactory 在解析配置文件时并不会初始化对象,只有在使用对象 getBean() 才会对该对象进行初始化,而 ApplicationContext 在解析配置文件时对配置文件中的所有对象都初始化了,getBean() 方法只是获取对象的过程。

ApplicationContext 是如何管理 Bean 呢?下面这个 Demo 简单模仿了这个原理:

建立一个类PersonServiceBean,并在xml文件中进行配置

public class PersonServiceBean implements PersonService   {  
    public void save(){  
        System.out.println("我是save()方法");  
    }  
}  
<bean id="personService" class="cn.itcast.service.impl.PersonServiceBean"></bean> 

建立类BeanDefinition,提供一个构造函数,将其作为每个bean的公共转型类

public class BeanDefinition {  
      
    private String id;    
    private String className;  
      
    public BeanDefinition(String id, String className) {  
        this.id = id;  
        this.className = className;  
    }  
  
    public String getId() {  
        return id;  
    }  
  
    public void setId(String id) {  
        this.id = id;  
    }  
  
    public String getClassName() {  
        return className;  
    }  
  
    public void setClassName(String className) {  
        this.className = className;  
    }  
}  

建立容器类 tgbApplicationContext

/** 
 * 测试spring容器 
 * @author hegang 
 * 
 */  
public class tgbClassPathXMLApplicationContext {  
      
    private List<BeanDefinition> beanDefines =new ArrayList<BeanDefinition>();  
    private Map<String,Object> sigletons =new HashMap<String,Object>();  
      
      
    public tgbClassPathXMLApplicationContext(String filename){  
        this.readXML(filename);  
        this.instanceBeans();  
    }  
  
    /** 
     * 完成bean的实例化 
     */  
    private void instanceBeans() {  
        for(BeanDefinition beanDefinition :  beanDefines){  
            try {  
                if(beanDefinition.getClassName()!=null && !"".equals(beanDefinition.getClassName().trim())){  
                  sigletons.put(beanDefinition.getId(),Class.forName(beanDefinition.getClassName()).newInstance());  
                }  
            } catch (Exception e) {  
                // TODO Auto-generated catch block  
                e.printStackTrace();  
            }  
              
        }  
          
    }  
  
    /** 
     * 读取xml配置文件 
     * @param filename 
     */  
    private void readXML(String filename) {  
        SAXReader saxReader = new SAXReader(); //创建读取器  
        Document document =null;  
        try{  
            URL xmlpath = this.getClass().getClassLoader().getResource(filename);  
            document =saxReader.read(xmlpath);  
            Map<String,String> nsMap =new HashMap<String,String>();  
            nsMap.put("ns","http://www.springframework.org/schema/beans"); //加入命名空间  
            XPath xsub = document.createXPath("//ns:beans/ns:bean"); //创建beans/bean查询路径  
             xsub.setNamespaceURIs(nsMap); // 设置命名空间  
            List<Element> beans = xsub.selectNodes(document); // 获取文档下所有的bean节点  
            for(Element element:beans){  
                String id =element.attributeValue("id"); // 获取id属性值  
                String clazz =element.attributeValue("class"); // 获取class属性值  
                BeanDefinition beanDefine =new BeanDefinition(id,clazz);  
                beanDefines.add(beanDefine);  
            }  
          
        } catch(Exception e){  
            e.printStackTrace();  
        }  
          
    }  
      
    /** 
     * 获取bean实例 
     * @param beanName 
     * @return 
     */  
    public Object getBean(String beanName){  
        return this.sigletons.get(beanName);  
    }  
}  

该类中拥有一个 List<BeanDefinition> 泛型集合类以及一个 Map<String,Object> 集合。通过查看代码我们知道这个容器类所做的事情如下:

  • 读取配置文件 bean.xml,并根据文件中 bean 的 id, class 属性实例化一个 BeanDefinition,装入泛型集合中
  • 通过循环+反射,将 List<BeanDefinition> 中的 bean 加入到 Map<String,Object> 中,这里用反射将 bean 中的 className 属性转换为一个实例化的 bean 对象加入到了 Map 中
  • 提供一个对外的接口,通过传入参数获取该 bean

下面就是通过容器类获取具体 bean 的代码了

public class SpringTest {  
    @Test  
    public void instanceSpring(){  
        tgbClassPathXMLApplicationContext ctx =new tgbClassPathXMLApplicationContext("beans.xml");    
        PersonService personService =(PersonService) ctx.getBean("personService");  
        personService.save();  
    }  
}

通过这样的 Demo,可以清楚看到 Spring 容器做的事情。它在初始化的时候将配置文件中 bean 以及相对应关系的配置都加入到 ApplicationContext,通过一系列的转换将这些 bean 实例化,bean 被它进行了管理,所以 ApplicationContext 就扮演了一个容器的角色。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Spring 如何管理 bean 的相关文章

随机推荐

  • 【c语言】利用指针求三个数的最大数和最小数

    比较费空间的笨方法 include
  • xtu 1397 Patchouli的金字塔

    题目描述 Patchouli想要绘制一个金字塔 金字塔的图案由n个正三角形和倒三角形堆叠而成 具体的绘制方法如下 每个三角形由 和 组成 分别代表三角形的顶点和三条边 第一行只包含一个正三角形 其余各行的三角形按照 正三角形 倒三角形 正三
  • STM32----ADC模数转换与DAC数模转换

    目录 ADC模数转换 DAC数模转换 ADC模数转换 指模 数转换器或者模拟 数字转换器 将连续变量的模拟信号转换为离散的数字信号的器件 典型的模拟数字转换器将模拟信号转换为表示一定比例电压值的数字信号 特点 STM32通道组 1 规则通道
  • 采用 Nacos 和 Apollo 作为配置中心时@ConfigurationProperties、@RefreshScope的正确用法

    心中剑 手中剑 剑起 剑来 剑魂 剑起 众所周知 当前各个互联网企业采用的配置中心中 无外乎 Nacos 和 Apollo 最为知名 今天不去比较优劣 因为适合自己的才是最好的 而是在两个框架出现过渡时 有些用法或者编码习惯需要调整 否则配
  • 配置MATLAB环境

    配置MATLAB环境 MATLAB是一种强大的数值计算和科学编程环境 它提供了许多功能和工具 用于数据分析 算法开发和模型仿真 在本文中 我将详细介绍如何配置MATLAB环境 步骤1 下载和安装MATLAB 首先 您需要从MathWorks
  • 哈希表(散列表)的平均查找成功/失败长度

    计算哈希地址的方法 称之为哈希函数 常见的计算哈希地址方法有 1 直接定址法 2 除留余数法 3 数字分析法 4 平方取中法 本文所分析的是使用除留余数法计算哈希地址这类 的平均查找成功长度和查找失败长度 对于除留余数法的哈希函数 散列函数
  • GB 9706.1-2020医疗设备爬电距离和电气间隙计算实例

    GB 9706 1 2020医疗设备爬电距离和电气间隙计算实例 本文只就所示路径的爬电距离 电气间隙的计算按照GB 9706 1 2020标准进行验证 路径的符合性或在文字中加以修改 不作判定 我们先来看案例背景 有上文可知 污染等级PD2
  • linux怎吗卸载openssh,卸载并重装openssh(解决ssh -1问题)

    在集群测试过程中 有一个节点的openssh装的有问题 需要ssh 1 才能登录 导致多节点的mpi无法使用 修改配置文件什么的也没有用 也许是我改的不对 最后决定直接重装openssh 1 卸载 先查看openssh的相关包 root n
  • 内存管理单元MMU简介(只有具有MMU才支持真正的操作系统,微软,linux,unix等)

    引言 MMU Memory Management Unit 即内存管理单元 是现代CPU架构中不可或缺的一部分 MMU主要包含以下几个功能 虚实地址翻译 在用户访问内存时 将用户访问的虚拟地址翻译为实际的物理地址 以便CPU对实际的物理地址
  • socket inet_pton

    inet pton Linux下这2个IP地址转换函数 可以在将IP地址在 点分十进制 和 整数 之间转换 而且 inet pton和inet ntop这2个函数能够处理ipv4和ipv6 算是比较新的函数了 inet pton函数原型如下
  • vue 打开一个新页面_vue如何打开新窗口

    项目中需要点击打开新页面另外展示数据 在vue中如何进行的 目前我能解决的就是只有一种方案 网上说的方案没有一种成功 为何呢 最主要原因是 app中只能有路由跳转 不能再有其他内容时才会打开时是全新的一个页面 否则就会新开页面内容与APP中
  • 《Roller: Fast and Efficient Tensor Compilation for Deep Learning》

    Roller Fast and Efficient Tensor Compilation for Deep Learning 用于深度学习 快速高效的张量编译器 作者 微软亚洲研究院以及多伦多大学等多所高校 摘要 当前编译为了产生高效的ke
  • 微服务链路追踪——skywalking

    前言 skywalking是分布式系统的应用程序性能监视 分布式链路追踪工具 跟听云 博瑞等一系列服务器监控组件服务类似 开源的相关类似组件有zipkin pinpoint等 由于笔者所在项目组准备升级springcloud 缺少相关链路监
  • [U3D] ShaderLab学习笔记(一) Shader的语法基础

    U3D ShaderLab学习笔记 一 Shader的语法基础 Shader的分类 Shader的代码构成 整体架构 代码分区介绍 ShaderLab的变量 基础变量类型 结构体struct 属性变量声明语法 Attribute Color
  • 【DRAM存储器四】DRAM存储器的架构演进-part1

    个人主页 highman110 作者简介 一名硬件工程师 持续学习 不断记录 保持思考 输出干货内容 参考书籍 Memory Systems Cache DRAM Disk 上篇文章我们分析了DRAM存储器的基本原理和现代DDR4的内部结构
  • 1.44寸TFT-LCD显示屏取模教程

    目录 1 软件包 点击下载 2 LCD ASCLL码取模教程 3 LCD汉字取模教程 4 LCD图片取模教程 1 软件包 点击下载 2 LCD ASCLL码取模教程 1 打开取模软件 2 左上角模式选择为字符模式 3 点击选项 4 设置如下
  • 计算机主机报警 声,电脑开机报警4声长鸣解决教程

    电脑开机报警是什么原因 首先要清理一下内存条 拆开主机后 用手指把内存插槽的卡子向两边扳动 拆除内存条 然后用橡皮筋擦擦 然后将内存条对准卡口 扶好内存条两端 稍稍用力按下安装内存条 然后开机看一下能不能启动电脑 电脑开机电脑图解 1 如果
  • 数据结构——双链表(C语言)

    目录 编辑 双链表的初始化 双链表的打印 双链表的尾插 双链表的头插 双链表的尾删 双链表的头删 双链表pos位置之前的插入 双链表pos位置的删除 关于顺序表和链表的区别 上篇文章给大家讲解了无头单向循环链表 它的特点 结构简单 一般不会
  • 69.android 简单的沉浸式状态栏,设置状态栏颜色,以及给小米手机设置状态栏文字颜色+取消状态栏,隐藏虚拟按键,并且全屏

    第一种 简单的方式 直接把状态栏顶掉 为透明色 在Activity里使用 if Build VERSION SDK INT gt Build VERSION CODES KITKAT int flagTranslucentStatus Wi
  • Spring 如何管理 bean

    本文转载自 https blog csdn net l18848956739 article details 80917853 常常听老师说容器 容器是什么 Spring 中是如何体现的 一直有疑惑 这两天看了一下Spring 管理 bea