【Spring(四)】万字详解bean的实例化

news2025/1/15 16:42:46

文章目录

  • 前言
  • 1.bean实例化
    • 1.1 bean的基础配置
    • 1.2 bean的实例化-构造方法
    • 1.3 bean的实例化-静态工厂
    • 1.4 bean的实例化-实例工厂与FactoryBean
  • 总结

前言

  在上篇文章,我们已经完成了入门案例的学习,在入门案例中,我们讲了三块东西,首先是bean怎么定义配置,DI怎么去制作配置以及我们的容器对象如何去获取在接下来的内容中,我们将针对以上三块东西展开学习✍️✍️。

1.bean实例化

1.1 bean的基础配置

  • 在学习bean的实例化之前,我们先来学习bean该如何配置

  在bean的配置这一块,我们将学习三块内容,分别为:bean基础配置、bean别名配置、bean作用范围配置

  • 我们先来看一下bean的基础配置👇👇
    在这里插入图片描述

  现在我们已经完成了基础配置的学习,id用来定义bean的名称,通过它可以获取,class用来指定bean的类型,也就是你造出来的bean究竟是哪一个类的,那么这个时候就有一个问题了,对应的bean的id你写好了,但是你的命名习惯和我的命名习惯不一样,我不想叫这个名称,有没有办法呢,这就是有关bean可以起多个名称,也就是所谓的bean的别名

  • 接下来我们来看bean的别名配置,在学习之前,我们先来交代一下当前的程序环境👇👇

  service层接口👇👇

在这里插入图片描述

  service层实现类👇👇

在这里插入图片描述

  dao层接口👇👇

在这里插入图片描述

  dao层实现类👇👇

在这里插入图片描述

  applicationContext.xml配置文件👇👇

在这里插入图片描述

  主方法👇👇

在这里插入图片描述

  • 在了解了程序环境以后,我们开始来学习别名配置🎉🎉。

  我们知道bean的别名肯定是写在applicationContext.xml配置文件中的 ,怎么写呢,在配置的 bean中,有一个name属性,可以为这个bean指定更多的名称👇👇。

在这里插入图片描述

  注意:别名可以有多个,使用逗号,分号,或者空格进行分隔。

  当我们在主方法中将getBean()方法里边的参数改为我们配置的别名,我们会发现程序还可以正常运行,那就说明我们配置的别名是有效的。👇👇

在这里插入图片描述
在这里插入图片描述

  接下来我们思考:我们在绑定service与dao的关系时,在service层配置的bean里边有一个属性ref表示的是参照dao层配置的bean,属性值为dao层配置的bean的属性id,那么如果我们将ref这个属性改为我们在dao层配置的bean的别名,那么程序还可以正常运行吗?我们来演示一下👇👇

在这里插入图片描述
在这里插入图片描述

  通过以上演示,我们可以得知别名的作用范围是很大的❗❗虽然我们学习了用别名配置bean的方式,但是还是建议我们ref参照的时候,还是引用id属性💪💪。

  • 接下来需要说一说我们需要注意的问题了👇👇

  回到我们的主方法中,我们现在在getBean()方法中传递进去一个我们没有的参数service5,这是在配置的service的bean中的id属性和name属性都没有的参数,那我们运行的话会有什么问题呢👇👇

在这里插入图片描述

  运行完会报出一个异常,这个异常的意思就是没有一个这样的bean被定义,如果以后我们遇到这个异常的话,只需要检查我们的名字就行了👊👊

在这里插入图片描述

  • bean的别名配置我们已经说完了,接下来我们来学习bean的作用范围👇👇

  什么叫bean的作用范围呢?其实就是你现在创建的bean的究竟是一个对象还是多个对象,什么意思呢,其实就是说你造的对象是单例的还是非单例的,我们先来看看如下代码👇👇

在这里插入图片描述

  我们获取到BookDao的对象,并且打印它的地址👇👇

在这里插入图片描述

  那我们将以上代码复制两份并且分别打印它们的地址,会出现什么结果呢👇👇

在这里插入图片描述
在这里插入图片描述

  通过运行结果我们可以发现,两次打印的结果是同一个地址,那么它们也可以认为是同一个对象了,由此得出:Spring默认给我们创建的bean是单例的,那么这时候就有新问题了,如果我想要创建一个非单例的该怎么办,这个时候就要通过配置的方法解决这个问题了🎉🎉

  如下,我们在dao层配置的bean后边再加一个属性scope,就是作用范围的意思,里边有两个值,一个singleton表示单例的,一个prototype表示非单例的,不写的话,默认是signleton,我们设置scope属性为prototype,来看看运行结果👇👇

在这里插入图片描述
在这里插入图片描述

  通过运行结果我们可以得出,此时的所创建的两个对象是不同的,注意:我们上面所框出的是对象的哈希值,不是对象的地址但是可以当做是对象的地址❗❗

  • 在学完bean的作用范围,我们可以认为它是可以控制创建的bean是一个或者是多个的,那么新的问题来了,为什么bean默认是单例的

  我们来解释一下,对于Spring来说,它帮我们管理的bean要放到它的容器中,我们 假定一个场景,如果它造出来的bean不是非单例的,那么这个bean的数量会有多少呢?它会无穷无尽,用一次造一个,所以说Spring它并不是帮我们管理这一类bean的,这样的话,对Spring容器来说也有一个非常大的压力,那Spring帮我们管理的bean都是单例的,那会对我们的业务造成伤害吗,你想一想,你造一个dao对象,执行完一个方法,下一次你又需要造一个dao对象,再执行另一个方法,那我这两个对象用同一个不行吗?好像没有什么问题,就是这个原因,Spring容器在帮我们管理对象的时候其实就是在管理那些你可以复用的对象,就是这个对象你用一次,下一次还用它,所以你下次还会从容器中拿,这样它的效率才会更高一些,因此,它就简单一点,给你造的bean就是单例的❗❗。

  • 那么新的问题有又来了,哪些bean适合造单例的呢❓

  我们的表现层对象,比如说我们现在写的Servlet,业务层对象, Service,数据层对象,Dao,或者还有一些工具类的对象,这些对象,你造一次就ok了,就这个对象我可以反复用,这些东西交给Spring管理💪💪。

  • 那哪些东西不适合交给Spring管理呢❓

  封装实体的域对象不适合交给Spring管理,因为它里边会记录一些它的成员变量的一些属性值,到这里我们就知道了bean的作用范围控制我们bean创建的实例的数量的🎈🎈。

1.2 bean的实例化-构造方法

  上面我们学习完了bean的基础配置,那就有人问了,我们的这个单例bean是如何造出来的呢,和我们以前的写法一样吗,也是用new的方式造出来的吗,我们现在就来学习bean的实例化-构造方法实例化的方式🎉🎉。

  对于bean来说,其本质是对象,在前面我们说过,我们将容器中管理的对象叫做bean,我们以前创造对象是怎么写:new跟构造方法,对于Spring来说,它也是通过构造方法来完成bean的创建的,一起来看一下👇👇

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

   以上是我们程序的环境☝️☝️,接下来我们来说以前我们造对象new+构造方法,对于Spring来说,同样的道理,它也是用构造方法来造对象的。

   接下来我们在dao的实现类中生成构造方法,并且在构造方法中打印一句话👇👇

在这里插入图片描述

   什么都不动,我们再来运行一下,看看这句话执行了没有,如果执行了,那就意味着Spring容器调用了构造方法造对象👇👇

在这里插入图片描述

   结果是用了,造对象都得用构造方法,在这说一个东西,我们将构造方法的权限修饰符改为private,我们说如果以前我们写程序,把构造方法私有化以后,我们在外边还可以造对象吗?显然是绝对造不出来的,那我们再来运行一下👇👇

在这里插入图片描述
在这里插入图片描述

   结果是不是出人意料啊,Spring还可以调用它的构造方法,那就说明了一点,Spring确实是通过构造方法来造对象的,而且不管是公共的还是私有的它都能调到,我们可以猜到它的内部是怎么回事吗,私有的东西它居然可以访问,怎么做的,是通过反射,后边我们在学习一些内部工作原理的时候,我们再来学习它,现在只需要知道它是通过构造方法造对象的就可以了,但是这个时候就有人提出来了一个问题,那万一给它加一个参数呢?👇👇

在这里插入图片描述

  我们来试一试,并且运行一下,会发现它已经不能正常运行了👇👇,这就说明了一点,Spring在创建bean的时候,调用的是无参构造方法,到这里我们就学习完了第一种实例化bean的方式,就是用构造方法来实例化对象❗❗

在这里插入图片描述

1.3 bean的实例化-静态工厂

  • 前面我们学习了用构造方法来实例化bean,接下来我们来说第二种方式,在学习第二种方式之前,我们先来回顾一个东西,我们在前边讲过,用工厂也可以造对象,我们先来看看程序环境👇👇
    在这里插入图片描述
    在这里插入图片描述
  • 接下来我提供了一个工厂类👇👇
    在这里插入图片描述
  • 如果用这个来写的话,会是什么样子的呢?接下来我们来看一下

  先去使用工厂去获得这个对象,然后去运行,我们去运行一下👇👇

在这里插入图片描述
在这里插入图片描述

  我们发现这是可以运行的,其实这是早些年做程序的一个常用的方式,说的简单一点就是造对象不要自己new,而是用工厂的方式做一定程度的解耦,那么这种方式也是造对象的一种方式,如果我们的对象是用这样一种方式造出来的,交给Spring管理该怎么管呢?这就是我们要学习的第二种方式:用静态工厂来造对象,接下来我们来学习以下该怎么做💪💪

  对于它的接口实现类和静态工厂来说,这三个东西是一套东西,如果我们现在要管理这个bean,首先要写它的配置文件👇👇,那么问题来了,这样造出来的对象究竟是dao的对象还是factory的对象❓应该是factory的,因为你配什么造出来的就是什么,那我们要的是factory的对象吗?显然不是,我们要的是factory里边的方法造出来的dao对象,所以我们下面这么写肯定是不行的,我们除了要告诉它的工厂类,还要告诉它一个东西factory-method属性来告诉它工厂是使用哪一个方法来造对象的,到这就可以造出来了,我们来运行一下,当然是用Spring的方式来运行的👇👇。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

  到这我们的第二种方式就学完了,但是还有一个问题,为什么不直接new啊,我们要知道工厂中做的有事情,可能会有一些配置👇👇,并且不能扔,所以强制你必须要用这个工厂,我们再来运行一下👇👇

在这里插入图片描述
在这里插入图片描述

1.4 bean的实例化-实例工厂与FactoryBean

  • 接下来我们来学习第三种方式,首先我们来看看程序环境👇👇。
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    注意:此时这个工厂是非静态的
    在这里插入图片描述
    在这里插入图片描述
  • 在了解完程序环境后,我们就开始学习它

  首先也是一样打开配置文件,我们在实例化的时候,必须先去造一个实例工厂类的对象,所以我们先来配置实例工厂类的bean👇👇

在这里插入图片描述

  我们在造出这个工厂类的对象以后,我们再来配置dao层的bean👇👇,属性factory-bean指的是这个工厂的实例在哪呢,第二个是这个工厂用哪个方法来造这个对象的👇👇。

在这里插入图片描述

  我们来用Spring的方式来运行一下👇👇

在这里插入图片描述
在这里插入图片描述

  上边我们为了造dao层的对象,专门写了一个factory的bean,其实这个东西挺多余的,除了这个作用以外,无任何意义,还有在dao层的bean里边有一个属性factory-method,方法名不固定,每个里边都得指定,那么这种东西不能写一个通用的名称吗?针对以上问题,Spring就做了一次改良:FactoryBean,我们先来看看程序环境👇👇

在这里插入图片描述
注意:工厂造什么对象,就写什么泛型,第二个方法返回的是对象的字节码文件.

  我们可能会发现,它和上边的好像没什么区别,但是它在配置的时候可简单多了,我们接下来在配置文件中配bean,并且看看是否可以正常运行👇👇

在这里插入图片描述
在这里插入图片描述

  结果是可以正常运行,这就是我们所说的第三种方式的改良了,在这里我们覆盖了一个方法isSingleton,那接下来我们来看看,既然你造出来这个对象了,我们可以想一想,造出来的这个对象是单例的还是非单例,我们来通过getBean()方法获得两个userDao对象,并且分别打印,接下来我们来看一下 👇👇

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

  我们通过结果可以看出,通过这种方式造出来的对象是单例的,那么怎么样去改非单例的呢,我们在UserDaoFactoryBean中加上isSingleton方法,然后返回值设置为false,就可以改成非单例的了💪💪

在这里插入图片描述

  我们再来运行一下,此时就变成非单例的了

在这里插入图片描述

总结

  在本篇文章中,我们先来介绍了bean的基础配置,然后详细介绍了几种实例化bean的方式,下篇文章我们将要学习bean的生命周期,最后,如果有什么错误的话,大家可以私信我📬📬,希望大家多多关注+点赞+收藏 ^_^🙏🙏,你们的鼓励是我不断前进的动力💪💪!!!

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

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

相关文章

《Kotlin核心编程》笔记:函数和Lambda表达式

高阶函数和lambda表达式 函数式语言⼀个典型的特征就在于函数是头等公民——我们不仅可以像类⼀样在顶层直接定义⼀个函数,也可以在⼀个函数内部定义⼀个局部函数,如下所示:所谓的高阶函数,你可以把它理解成“ 以其他函数作为参数…

Debian10,docker单机安装ThingsBoard-3.3.2

1.编译项目源码 源代码编译ThingsBoard-3.3.2 2.环境准备 修改ssh登录配置 sudo vi /etc/ssh/sshd_config 打开密码登录和root用户登录3.安装docker 更新apt sudo apt update安装必备软件 sudo apt install apt-transport-https ca-certificates curl gnupg2 software-p…

SpringBoot异步方法(官方案例)

在线文档项目结构 1.源码克隆:git clone https://github.com/spring-guides/gs-async-method.git 2.包含两个项目initial和complete,initial可以根据文档练习完善,complete是完整项目 3.功能描述:构建查找服务,异步查询…

Linux搭建Docker版FTP,命令与Dockerfile两种方式以及容器编码解决

Linux搭建Docker版FTP,命令与Dockerfile两种方式以及容器编码解决一、Linux搭建Docker版FTP二、修改 Docker 容器内部 locale 系统编码最终待实现效果,这个方式容器内部编码并未永久改变三、编写Dockerfile方式加载带UTF-8编码环境的镜像3.1Dockerfile构…

【LINUX权限】

目录:前言一、shell二、权限(一)文件权限(二)权限相关指令chmod(修改权限)su 、sudo(提权)root提权chown 、chgrpumask(掩码)file(三&…

性能测试工具 Lmbench 的使用方法以及解析运行结果

1. Lmbench 简介 Lmbench 是一款简易可以移植的内存测试工具,其主要功能有,带宽测评(读取缓存文件、拷贝内存、读/写内存、管道、TCP),延时测评(上下文切换、网络、文件系统的建立和删除、进程创建、信号处…

MYSQL中的14个实用的功能

1.group_concat 在我们平常的工作中,使用group by进行分组的场景,是非常多的。 比如想统计出用户表中,名称不同的用户的具体名称有哪些? 具体sql如下: select name from `user` group by name; 但如果想把name相同的code拼接在一起,放到另外一列中该怎么办呢? 答:…

Genesis一款基于Domino的app store应用超市

大家好,才是真的好。 众所周知,App Store是苹果iOS系统生态成功的关键因素。Domino作为一款企业应用平台,很多年前,就有人提出要创建Domino平台上的App Store。 其实比IOS早很多年前就有类似的应用管理,早在2000年的…

代码随想录之回溯第一课

要领:类型题目,用具体的一个例子来记忆,就够了,印象更加深刻。 一个题目,感觉理解不深刻,不透彻,不清晰,不熟练,就是不达标。 怎么做? 每天回顾复习看一次&am…

DD-1/50 12.5-50mA【接地继电器】

系列型号: DD-1/40接地继电器 DD-1/50接地继电器 DD-1/60接地继电器 一、 用途及工作原理 DD-1型接地继电器为瞬时动作的过电流继电器,用作小电流接地电力系统高电压三相交流发电机和电动机的接地零序过电流保护。继电器线圈接零序电流互感器(电缆式、…

电脑重装系统后分辨率不对应该怎么调

越来越多的小伙伴使用小白一键重装系统给自己的电脑安装上了win10系统,但是有部分小伙伴发现安装完win10系统之后,屏幕分辨率也无法进行调整,呈灰色状态。接下来小编就给大家详细的介绍一下小白一键重装系统分辨率不对怎么调的教程。 工具/原…

【Django】(一)基础知识

文章目录一.安装二.创建项目三.项目介绍四.APP的创建五.小案例六 模板和静态文件模板静态文件7.模板语法7.1 变量7.2列表7.3 字典7.4 过滤器7.5 if/else7.6 for标签7.7 ifequal和ifnotequal7.8注释7.9csrf_token8.模板继承8.1父模板8.2 子模板9.请求和响应10.数据库10.1安装第三…

【服务器搭建个人网站】附:接入的服务商 以及 安全评估报告该如何填写?

前言 哈喽,大家好,我是木易巷! 关于公安备案的一些详细的细节没有分享出来,在公安备案期间要填写很多东西,其中比较难填写的就是接入的服务商和安全评估报告的填写。 这一篇给大家总结:公安备案接入服务商和…

⭐️【linux】关于linux-gcc,你必须要知道的知识

🌲🌲目录🌲🌲 1️⃣什么是gcc 2️⃣gcc如何生成可执行文件 3️⃣简单使用gcc 4️⃣linux的库 1️⃣什么是gcc ❄️GCC(GNU Compiler Collection,GNU编译器套件),是由 GNU 开发的…

Java 中 Map 集合的基本使用

一、HashMap 1.1 HashMap 基本使用 import java.util.*;/*** author: yunhu* date: 2022/7/14*/ public class Test {public static void main(String[] args) {Map<String, Integer> map new HashMap<>();map.put("Alice", 12);map.put("Bob&qu…

62.Python 类的3要素语法

62.类的3要素语法 文章目录62.类的3要素语法1. 定义类的语法2. pass语句的作用3.我们学的5个缩进语法4.类的属性5.类的方法6. 创建对象7.类在爬虫中的应用8. 总结1. 定义类的语法 定义类的语法如下&#xff1a; class 类名: 代码块 从语法上来看&#xff1a;类的…

Edify Script (Android Shell)定制Twrp刷机包

本文将通过三方面向大家介绍Edify Script,相信你看完了这篇文章会对安卓系统可刷写插件有一个比较完整的认识,并且能过通过阅读此文章实现使用twrp刷入自己写的插件zipi包。网上能搜到的大部分是旧的,新版本去掉了很多的edify函数,照着他们那个写多半会报错。 本文分为如下…

LeetCode学习-第三十八天

第三十八天 我使用的C&#xff0c;错误的地方请见谅&#xff0c;文章初衷仅用来督促本人学习&#xff0c;如果恰巧能够给你带来帮助&#xff0c;我会十分开心。 文章目录第三十八天一、537. 复数乘法二、29. 两数相除一、537. 复数乘法 复数 可以用字符串表示&#xff0c;遵循…

CentOS7如何修改IP地址及UUID

CentOS7系统下&#xff0c;如果要把IP地址修改为192.168.1.80&#xff0c;子网掩码是255.255.255.0&#xff0c;网关是192.168.1.1&#xff0c;DNS是192.168.1.1&#xff0c;那么我们使用客户端连接CentOS或者打开系统终端&#xff0c;切换到root用户&#xff0c;命令&#xff…

开料的目的和子流程,一文读懂

经过多个月的分享&#xff0c;关于PCB行业&#xff0c;想必朋友们已经有了一些个人的理解&#xff0c;甚至对PCB行业&#xff0c;还产生了浓厚的兴趣。 但是&#xff0c;PCB生产工艺是非常复杂的&#xff0c;想要深入地学习并且学好PCB生产工艺&#xff0c;假如不在PCB的生产一…