Spring学习:二、Bean的管理

news2024/11/15 11:21:04

4. Bean的管理

​ Spring的基本Bean管理包括Bean配置,Bean实例化和Bean的依赖注入。这些管理可以通过手工编码的方式把每个Bean注册到容器中,也可以通过properties文件和xml文件配置Bean和Bean之间的依赖关系。通常我们的配置方式是XML作为配置文件。

4.1 Bean的配置

​ 我们可以看一看前面例子的配置文件:

<bean id="dog" class="org.suke.Dog" ></bean>
<bean id="cat" class="org.suke.Cat" ></bean>
<bean id="boy" class="org.suke.Boy" >
   <property name="pet" ref="dog"></property>
</bean>

配置一个Bean,id为Bean的标识,在配置Bean时,可以使用name属性为Bean指定标识。id 和name 属性都是用来指定bean的标识符。id具有唯一性,并且是XML中真正的id属性,XML解析器可以验证其的合法性,在使用中必须和Java中命名变量一样去命名id的值,比如不能以数字开始等约束。name属性值则没有要求,甚至在name中可以使用特殊字符(如等)。

​ 如果在配置文件中既没有配置id,也没有配置name,Spring会默认使用类的全名来标识,如果需要配置多个类名相同的对象,则spirng会使用 类名+#+数字的形式来标识。即如果配置了三个<bean class="org.suke.Dog">,那么标识分别是 “org.suke.Dog”” org.suke.Dog #1”,和” org.suke.Dog #2”

​ name属性其实就是为该Bean指定的别名,多个别名之间使用”,”进行分隔。还可以使用< alias >来指定别名,比如上面的dog使用alias来配置别名可以做如下配置:

<bean id="dog" name="dog1,dog2,dog3" class="org.suke.Dog" />

<alias name="dog" alias="dog4"/>

​ 这样dog对象就被被标识为 dog,dog1,dog2,dog3,dog4这4个标识名,<alias>标记中的name可以是id的值,也可以是name的值(也就是说使用别名还可以再次重新命名),那么在程序中我们通过ApplicationContext对象或者BeanFactory的get方法获取bean对象的时候,就可以使用dog,dog1,dog2,dog3,dog4这4中标识中的任意一个来获取bean对象,获取到的bean对象都是同一个对象。

class是Bean的全限定名。

配置Bean的属性,name表示属性名,这个属性实际上是javaBean的setter方法,所以配置的类必须符合javaBean的规范。

④<property>节点可以通过ref属性引用其他已经配置的Bean,ref的值是其他已经配置Bean的标识。如果这个属性的值是基本数据类型或者是String类型,只要该属性具有setter访问器,就可以使用value直接设置值。

4.2 Bean的作用域(scope)

​ 配置文件中的Bean实例化后,该如何保存,就是Bean的作用域问题。比如:默认的作用域是singleton,表示对应Bean在容器中是单例的,整个系统只保存一份实例,实例化后即保存起来,直到系统结束才销毁,期间所有线程共享一份实例。Bean的作用域使用<bean>节点的scope属性来表示。

​ scope:指对象的作用范围,取值如下:

取值范围说明
singleton默认值,单例的
prototype多例的
requestWEB 项目中,Spring 创建一个 Bean 的对象,将对象存入到 request 域中
sessionWEB 项目中,Spring 创建一个 Bean 的对象,将对象存入到 session 域中
global sessionWEB 项目中,应用在 Portlet 环境,没有 Portlet 环境globalSession 相当于session

重点是singleton与prototype两个作用域:

1)当scope的取值为singleton时

Bean的实例化个数:1个

Bean的实例化时机:当Spring核心文件被加载时,实例化配置的Bean实例

Bean的生命周期:

  • 对象创建:当应用加载,创建容器时,对象就被创建了

  • 对象运行:只要容器在,对象一直活着

  • 对象销毁:当应用卸载,销毁容器时,对象就被销毁了

2)当scope的取值为prototype时

Bean的实例化个数:多个

Bean的实例化时机:当调用getBean()方法时实例化Bean

  • 对象创建:当使用对象时,创建新的对象实例

  • 对象运行:只要对象在使用中,就一直活着

  • 对象销毁:当对象长时间不用时,被 Java 的垃圾回收器回收了

public class HelloImpl implements IHello {
    public String sayHello(String word) {
        return "hello:"+word;
    }

    public HelloImpl() {
        System.out.println("HelloImpl实例进行初始化....");
    }
}
<bean class="com.suke.hello.impl.HelloImpl" id="hello" scope="singleton"></bean>

测试代码:

 @Test
    public void testScope(){
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
        IHello hello = applicationContext.getBean("hello", IHello.class);

        IHello hello2 = applicationContext.getBean("hello", IHello.class);
        System.out.println("是否是同一个对象:"+(hello == hello2));
    }

测试结果:
在这里插入图片描述

现在我们把HelloImpl的bean设置为prototype,再来测试,看控制台的效果:

<bean class="com.suke.hello.impl.HelloImpl" id="hello" scope="prototype"></bean>

在这里插入图片描述

4.3 Bean的生命周期的配置

我们可以在Bean标签中使用init-method属性和destroy-method属性对bean的生命周期进行相关配置:

  • init-method:指定类中的初始化方法名称

init-method用于指定bean的初始化方法。 我们知道spring会帮我们实例化对象,实例化对象之后,spring就会查找我们是否配置了init-method如果配置了,spring就会调用我们配置的initmethod方法,进行bean的初始化。

  • destroy-method:指定类中销毁方法名称

destroy-methodinit-method一样,只是它是用来配置释放资源的方法,spring会在销毁当前bean对象之前调用destroy-method制定的方法。

package com.suke.hello.impl;

import com.suke.hello.IHello;

public class HelloImpl implements IHello {
    public String sayHello(String word) {
        return "hello:"+word;
    }

    public HelloImpl() {
        System.out.println("HelloImpl实例进行初始化....");
    }

    public void init(){
        System.out.println("哈哈,我出生了...");
    }

    public void destroy(){
        System.out.println("555,我要走了...");
    }
}

<bean class="com.suke.hello.impl.HelloImpl" id="hello"  init-method="init" destroy-method="destroy"></bean>

测试代码:

@Test
public void testLife(){
    AbstractApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
    IHello hello = applicationContext.getBean("hello", IHello.class);
    hello.sayHello("spring");
    applicationContext.close();
}

测试效果:
在这里插入图片描述

4.4 Spring Bean 的加载流程概述

​ Spring 作为 Ioc 框架,实现了依赖注入,由一个中心化的 Bean 工厂来负责各个 Bean 的实例化和依赖管理。各个 Bean 可以不需要关心各自的复杂的创建过程,达到了很好的解耦效果。

​ springBean的加载过程大致分为两个过程:解析注册,实例化
在这里插入图片描述

​ spring先解析xml文件或者注解配置,读取所有要加载类信息。根据类信息创建对应的BeanDefinition对象,再根据Beandefination对象创建实例对象。

​ BeanDefinition是SpringBean的描述对象,主要封装了如下信息:

在这里插入图片描述

Spring通过BeanDefinition来进行bean的实例化, 实例化的bean存在BeanFactory的singletonObjects中
在这里插入图片描述

4.5 依赖注入属性配置

4.5.1 依赖注入二种方式

​ 在DI的案例中,我们在UserService中是怎么把UserDao注入进来的呢?其实在Spring中提供了两种注入方式:

  • Set方法的注入
  • 构造方法的注入
4.5.1.1 属性setter方法注入

通过 <property>元素,实现属性setter方法注入

package com.suke.injection;

public class Dog {
    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

package com.suke.injection;

public class Person {
    private String name;
    private Dog dog;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Dog getDog() {
        return dog;
    }

    public void setDog(Dog dog) {
        this.dog = dog;
    }
}

配置:

 <bean id="d1" class="com.suke.injection.Dog">
     <property name="name" value="旺财"/>
 </bean>

我们在使用property和constructor-arg为bean注入属性时,如果属性是简单类型,我们可以通过value直接注入。

这里简单类型主要是指java的基本类型和String型

<bean id="p1" class="com.suke.injection.Person">
    <property name="name" value="张三"/>
    <property name="dog" ref="d1"/>
</bean>

当我们通知spring帮我们注入某个引用对象时,我们可以使用ref通知spring注入bean的beanName

4.5.1.2 P命名空间使用

​ Spring2.5 版本之后,为了简化属性setter依赖注入,提供虚拟名称空间 p ,使用步骤:

  1. 在spring的配置文件中<beans>标签引入p命令空间

     xmlns:p="http://www.springframework.org/schema/p"
    

在这里插入图片描述

  1. 使用p命令空间

    <bean id="d2" class="com.suke.injection.Dog">
            <property name="name" value="来福"/>
    </bean>
    <bean id="p2" class="com.suke.injection.Person" p:name="李四" p:dog-ref="d2"></bean>
    
    
4.5.1.3 构造方法注入

​ 通过 <constructor-arg> 进行构造器参数注入

​ 我们分别在Dog类和Person类提供了无参和有参的构造方法

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3Noixp5l-1669895043785)(assets/image-20220731173131884.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aKRWGN31-1669895043787)(assets/image-20220731173159237.png)]

配置:

<bean id="d3" class="com.suke.injection.Dog">
    <constructor-arg name="name" value="大黄"/>
</bean>

<bean id="p3" class="com.suke.injection.Person">
    <constructor-arg name="name" value="王五"/>
    <constructor-arg name="dog" type="com.suke.injection.Dog" index="1" ref="d3"/>
</bean>

<constructor-arg>标签属性说明:

  • name: 属性名
  • type: 属性类型
  • index: 参数索引(从0开始)

4.5.2 集合属性的注入

​ 某些类的属性是可能是集合,包括:数组LISTMAPSETPROPERTIES等集合,在Spring中同样可以使用XML配置文件的方式对属性进行注入。

主要用于 参数配置 !

  • 数组或者List ----- <list>或者 <array>注入

  • Set ---- <set> 注入

  • Map — <map> <entry> 注入

  • Properties — <props> <prop> 注入

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZQslqlYO-1669895043787)(assets/image-20220731181126728.png)]

配置:

  <bean id="p4" class="com.suke.injection.Person">
        <property name="list">
            <list>
                <value>aaa</value>
                <value>bbb</value>
                <value>aaa</value>
                <value>ccc</value>
            </list>
        </property>
        <property name="set">
            <set>
                <value>aaa</value>
                <value>bbb</value>
                <value>aaa</value>
                <value>ccc</value>
            </set>
        </property>
        <property name="map">
            <map>
                <entry key="abc" value="123"></entry>
                <entry key="bcd" value="456"></entry>
                <entry key="efg" value="567"></entry>
            </map>
        </property>
        <property name="props">
            <props>
                <prop key="zhangsan">张三</prop>
                <prop key="lisi">李四</prop>
                <prop key="wangwu">王五</prop>
            </props>
        </property>
    </bean>

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

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

相关文章

基于纳芯微产品的尾灯方案介绍

文章目录1.前言2.方案简介2.1 概述2.2 功能介绍2.3 DEMO资料3.主要器件介绍3.1 LED Driver3.2 LDO3.3 CAN\LIN收发器4.演示视频5.推荐阅读1.前言 最近拜访一些做尾灯模组的客户了解到&#xff0c;目前LED Driver依然紧缺&#xff0c;特别是TPS929120&#xff0c;BD18331这些差…

网络编程,UDP通信程序,TCP通信程序

一、网络编程 网络编程概述 网络编程 : 在网络[通信协议]下&#xff0c;不同计算机上运行的程序&#xff0c;可以进行[数据传输] 思考&#xff1a; A电脑中的QQ&#xff0c;发送消息给B电脑中的QQ。那么需要知道[哪些条件]才能发送&#xff1f; 在这个故事场景下&…

GitHub 的基本使用

文章目录一、使用前工作二、GitHub 的基本使用一、使用前工作 下载 uu 加速器&#xff0c;用于访问 GitHub 网站&#xff08;有魔法工具的小伙伴请忽略&#xff09;&#xff1b;uu 加速器下载安装完毕后搜索框搜索学术资源并点击加速&#xff08;如图1.2.1&#xff09;&#xf…

【Android App】人脸识别中使用Opencv比较两张人脸相似程度实战(附源码和演示 超详细)

需要全部代码请点赞关注收藏后评论区留言私信~~~ 一、比较两张人脸的相似程度 直方图由一排纵向的竖条或者竖线组成&#xff0c;横轴代表数据类型&#xff0c;纵轴代表数据多少。 图像直方图经常应用于特征提取、图像匹配等方面。 假设有两幅图像&#xff0c;它们的直方图很相…

Vue项目devServer.proxy代理配置详解

Vue项目devServer.proxy代理配置详解目录概述需求&#xff1a;设计思路实现思路分析1..config.js文件中&#xff0c;引入依赖项2.devServer.proxy 可以是一个指向开发环境 API 服务器的字符串3.更多控制行为参考资料和推荐阅读Survive by day and develop by night. talk for i…

语言模型也会“地域黑”?实验表明ALBERT最能黑,BART最友善

文 | ZenMoore前言今天我们来谈论一个不那么硬核的问题&#xff1a;预训练语言模型中的歧视与偏见(bias)。这个问题虽然不像技术问题那样核心&#xff0c;但仍然非常重要。想象一下&#xff1a;你接到了一笔外交级别的订单&#xff0c;要做一个生成语言模型&#xff0c;先不论效…

NNDL 实验七 循环神经网络(3)LSTM的记忆能力实验

文章目录6.3 LSTM的记忆能力实验6.3.1 模型构建6.3.1.1 LSTM层6.3.1.2 模型汇总6.3.2 模型训练6.3.2.1 训练指定长度的数字预测模型6.3.2.2 多组训练6.3.2.3 损失曲线展示【思考题1】LSTM与SRN实验结果对比&#xff0c;谈谈看法。&#xff08;选做&#xff09;6.3.3 模型评价6.…

Android OpenGL ES 学习(六) – 使用 VBO、VAO 和 EBO/IBO 优化程序

OpenGL 学习教程 Android OpenGL ES 学习(一) – 基本概念 Android OpenGL ES 学习(二) – 图形渲染管线和GLSL Android OpenGL ES 学习(三) – 绘制平面图形 Android OpenGL ES 学习(四) – 正交投屏 Android OpenGL ES 学习(五) – 渐变色 代码工程地址&#xff1a; https://…

【ARIMA时序预测】基于ARIMA实现时间序列数据预测附matlab代码

✅作者简介&#xff1a;热爱科研的Matlab仿真开发者&#xff0c;修心和技术同步精进&#xff0c;matlab项目合作可私信。 &#x1f34e;个人主页&#xff1a;Matlab科研工作室 &#x1f34a;个人信条&#xff1a;格物致知。 更多Matlab仿真内容点击&#x1f447; 智能优化算法 …

Unity常用的三种拖拽方法(内置方法 + 接口 + Event Trigger组件)

目录 内置方法OnMouseDrag【对象含有Collider组件】 配对小游戏 Event Trigger组件 接口 窗口小案例 内置方法OnMouseDrag【对象含有Collider组件】 OnMOuseOver()检测鼠标是否进入到这个2D贴图 当鼠标进入或离开2D贴图&#xff0c;会相应的放大、缩小 private void OnMo…

[附源码]计算机毕业设计springboot校园快递柜存取件系统

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

山外山通过注册:拟募资12亿 大健康与华盖信诚是股东

雷递网 雷建平 12月2日重庆山外山血液净化技术股份有限公司&#xff08;简称&#xff1a;“山外山”&#xff09;日前通过注册&#xff0c;准备在科创板上市。山外山计划募资12.47亿元&#xff0c;其中&#xff0c;8.63亿用于血液净化设备及高值耗材产业化项目&#xff0c;1.64…

【Python基础系列】Part2. 列表

二、列表 1.列表介绍 定义&#xff1a;列表是由一系列按照一定顺序排列的元素组成。 Python中用[]表示列表&#xff0c;用,分割元素。 number ["one", "two", "three"] print(number)# [one, two, three]列表中的元素可以是不同类型 numbe…

netsh interface portproxy端口转发,从本地端口到本地端口不起作用的解决办法

开启IP V6 你虽然可能用不到IPV6,但是有些系统是需要用到IPV6的dll来做端口转发的. 如图,确保你联网的连接已经开启 IPV6 检查IP Helper服务 打开任务管理器 点击 服务 查看iphlpsvc是否启动状态,点击右键如果显示的是停止,就是已经启动了. 如果显示"启动服务"则…

drools规则引擎并发结果不准确问题记录

思路 首先&#xff0c;drools的整体思路比较简单&#xff0c;一个是加载&#xff0c;一个是执行&#xff01; 加载&#xff1a;把一个比较复杂的关系运算想办法放到drools里面&#xff01; 执行&#xff1a;让drools去计算这个复杂的运算&#xff0c;最终我们只需要取结果就好&…

广域网技术——SR-MPLS技术基础理论讲解

目录 SR-MPLS基础概念 使用Segment Routeing MPLS技术的优点 Segment Routeing MPLS的基本原理 SRGB Segment ID Bind SID 粘连标签 OSPF对于SR-MPLS的扩展 OSPF对邻接SID做了细分 10类LSA定义的TLV类型 10类LSA定义的TLV的报文格式 ISIS对SR-MPLS的扩展…

详解设计模式:模版方法模式

模板方法模式&#xff08;Template Method Pattern&#xff09;也被称为模板模式&#xff08;Template Pattern&#xff09;&#xff0c;是在 GoF 23 种设计模式中定义了的行为型模式。 模板方法模式 定义一个操作中的算法骨架&#xff0c;而将一些步骤延迟到子类中。模板方法使…

若依框架RuoYi项目运行启动教程【傻瓜式教程】

启动若依项目 1.官网下载代码 若依官网 若依在线文档 首先去官网下载代码 链接到码云下载&#xff0c;要么用git下载要么压缩包下载。 然后再IDEA打开项目 想要运行就要搭建好环境 2.搭建若依环境 按照文档要求配置环境 JDK > 1.8 (推荐1.8版本) Mysql > 5.7.0 (推…

Stable Diffusion 2.0 来了

Stable Diffusion 一经发布&#xff0c;就立刻在业界掀起巨大的波浪。我个人后知后觉&#xff0c;直到 Stable Diffusion V1.4 版本发布&#xff0c;才接触 Stable Diffusion (之前使用的是 Disco Diffusion)。这段时间&#xff0c;SD 团队也没闲着&#xff0c;很快就发布了 V2…

【华为上机真题 2022】停车场车辆统计

&#x1f388; 作者&#xff1a;Linux猿 &#x1f388; 简介&#xff1a;CSDN博客专家&#x1f3c6;&#xff0c;华为云享专家&#x1f3c6;&#xff0c;Linux、C/C、云计算、物联网、面试、刷题、算法尽管咨询我&#xff0c;关注我&#xff0c;有问题私聊&#xff01; &…