Spring 项目创建和使用2 (Bean对象的存取)

目录

一、创建 Bean 对象

二、将Bean对象存储到 Spring容器中

三、创建 Spring 上下文(得到一个Spring容器)

 1. 通过在启动类中 ApplicationContext 获取一个 Spring容器

 2. 通过在启动类种使用 BeanFactory 的方式来得到 Spring 对象 (此时获取 Bean 的路径也要保持一致)

四、从 Spring 容器中获取到 Bean 对象(并使用Bean对象)

1. 通过名称(.xml文件中设置的 id )

     使用Applicationcontext 和 BeanFactory 的区别

  (1)所以二者的区别之一:

  (2)第二个区别:

 2. 通过类型的方式获取 Bean 对象

 3. 通过名称 + 类型的方式获取 Bean 对象

(1)先在.xml 文件中存储两个相同的 Bean 对象,然后再进行验证。

 四、什么是DI(依赖注入)


前言

    上一篇文章已经详细介绍了如何创建一个 Spring 项目,在创建好了 Spring 项目之后,就需要使用 Spring 容器存储和获取 Bean 对象了。 

    (Bean对象:在Java中,如果一个对象被使用多次,此时就可以成这个对象为 Bean 对象)

一、创建 Bean 对象

public class Student {private void sayHi() {System.out.println("Hii student");}
}

二、将Bean对象存储到 Spring容器中

    此时存储 Bean 对象是要依赖于xml配置文件的,里面要有一些配置信息,之后才能将 Bean对象存储到 Spring 容器中,如下图:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:content="http://www.springframework.org/schema/context"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd"><content:component-scan base-package="com.bit.service"></content:component-scan>
</beans>

    之后将上述代码复制到创建的配置文件 spring-config.xml 文件中

     在上述配置文件中添加下边代码:

 <!--将 bean对象(com.spring.demo.Student)存到spring容器中,他的名称叫做student --><bean id="student" class="com.spring.demo.Student"></bean>

    此时就把一个 Bean 对象(Student类)存储到 Spring 中了,接下来就是取出 Bean 对象了。

三、创建 Spring 上下文(得到一个Spring容器)

    要想得到一个 Spring 容器有两种方式:

1.
ApplicationContext context = newClassPathXmlApplicationContext("spring-config.xml");
2. 
//1. 得到Spring上下文对象
BeanFactory beanFactory =new XmlBeanFactory(new ClassPathResource("spring-config.xml"));

 1. 通过在启动类中 ApplicationContext 获取一个 Spring容器

    此时需要注意:参数中的配置路径就是.xml 文件的名称,只有设置了这个文件名称,在程序运行的时候才会去这个文件中将 Bean 对象存储到 Spring 容器中。 

 2. 通过在启动类种使用 BeanFactory 的方式来得到 Spring 对象 (此时获取 Bean 的路径也要保持一致)

四、从 Spring 容器中获取到 Bean 对象(并使用Bean对象)

    获取 Bean 对象有三种方式:用的方法都是一样的,只是getBean()方法的传的参数不同

1. 通过名称获取
2. 通过类型获取
3. 通过名称 + 类型的方式获取

1. 通过名称(.xml文件中设置的 id )

//2. 从Spring容器中获取到Bean对象Student student = (Student) context.getBean("student");//3.使用Bean对象student.sayHi();

    此时需要  注意:getBean方法中的参数是 Bean 对象中的名称,此时需要和 spring-config.xml 文件中的 Bean 对象的 id 设置的名称保持相同。

    获取 Bean 对象之后我们可以使用 Student 类的sayHi方法证明以下  Bean 对象是否可以正常使用:

    使用BeanFactory的方式获取并使用 Bean对象

     使用Applicationcontext 和 BeanFactory 的区别

    此时再创建一个新的Teacher类,然后在Student 和 Teacher 类中都加上构造方法,如下代码:

public class Student {public Student() {System.out.println("do student init");}public void sayHi() {System.out.println("Hii student");}
}public class Teacher {public Teacher() {System.out.println("do teacher init");}public void sayHi() {System.out.println("Hii Teacher");}
}

     此时再去用 ApplicationContext 和 Beanfactory就可以看到以下运行结果:

    在App中并没有获取 Teacher 对象,但是此时却加载了 Teacher 类的构造方法,而BeanFatory只会在 getBean() 方法调用了之后才会加载初始化 Student 对象。

  (1)所以二者的区别之一:

    在使用 ApplicationContext 时是饿汉模式,当得到一个 Spring 容器的时候就初始化了所有的 Bean 对象的,但是使用 BeanFactory 时是懒汉模式(非必要不加载),也就是只有在获取 Bean 对象的时候才会去初始化这个对象。

    这也是一个历史性的原因,在早期内存是比较昂贵的时候,是没有很大的存储空间,在一开始就初始化很多 Bean 对象的,但是随着后来的内存的价格相对不是很昂贵了,此时也就有多余的内存空间来存储很多的 Bean 对象了,尽管 Spring 是一个容器,但是底层存储的 Bean 对象本质还是在内存上存储的。

ApplicationContext的优点和缺点:   一次 Spring 容器的加载,就会初始化里面的所有 Bean 对象,后续在读取 Bean 对象读取的就会非常快; 性能较高,但是同样的也会比较耗费内存。
BeanFactory的优点和缺点:  是在getBean() 方法调用之后才会加载初始化 Bean 对象,所以性能比较低; 但是节省内存。

  (2)第二个区别:

    BeanFactory 是 ApplicationContext 的一个子类,所以ApplicationContext是后来有的,基于 BeanFactory又拓展了新的功能特性。

    按下F4键之后,我们可以看到如下图:

 

 2. 通过类型的方式获取 Bean 对象

    虽然通过名称是可以获取到 Student 对象,但是需要强转之后才能获取,因为 getBean 方法的返回值是一个Object类型的,所以用 Student 类型的去接收返回值就需要强制类型转换;所以代码看起来好像不是很优雅,此时就可以通过对象的类型来获取一个 Bean 对象。

Student student = context.getBean(Student.class);//根据类型获取

    此时的运行结果如下:

     但是这种方式获取Bean 对象也是有问题的;如果此时有两个同类型的 Bean 对象,此时再去通过类型的方式来获取Bean 对象就会报如下图的错误,因为类型一样时,程序不知道该获取哪一个对象,所以此时虽然不用强转了,但是同类型的 Bean 对象只能有一个。

 3. 通过名称 + 类型的方式获取 Bean 对象

    首先注意一个问题:如果在 Spring 容器中存储同一个对象,存储两份,此时是有两个对象呢,还是只有一个对象,另一个对象的引用指向了第一个对象呢?

(1)先在.xml 文件中存储两个相同的 Bean 对象,然后再进行验证。

 运行结果:

     也就是说首先是允许存储两个相同的 Bean 对象的,但是此时结果是false,所以是在 Spring 容器中存储了两份 Bean 对象的。(每一次存储 Bean 对象的时候,不会因为类型相同就只创建一个对象)

    根据名称 + 类型的方式来获取Bean 对象也是可以的,如下图结果:

 四、什么是DI(依赖注入)

Student student = context.getBean("student",Student.class);//根据类型获取

    上述代码就是依赖注入,就是DI,上一篇文章讲到IoC是一种思想,DI就是它的一种具体的实现方式,所以上面代码就是在程序运行的过程中动态的将 student 对象动态注入到当前运行的动态类中。

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C# Linq 详解一

目录 一、概述 二、Where 三、Select 四、GroupBy 五、First / FirstOrDefault 六、Last / LastOrDefault C# Linq 详解一 1.Where 2.Select 3.GroupBy 4.First / FirstOrDefault 5.Last / LastOrDefault C# Linq 详解二 1.OrderBy 2.OrderByDescending 3.Skip 4.Take …

第一百零六天学习记录:数据结构与算法基础:单链表(王卓教学视频)

线性表的链式表示和实现 结点在存储器中的位置是任意的&#xff0c;即逻辑上相邻的数据元素在物理上不一定相邻 线性表的链式表示又称为非顺序映像或链式映像。 用一组物理位置任意的存储单元来存放线性表的数据元素。 这组存储单元既可以是连续的&#xff0c;也可以是不连续的…

C#生成类库dll以及调用实例

本文讲解如何用C#语言生成类库并用winform项目进行调用 目录 创建C#类库项目 Winform调用dll 创建C#类库项目 编写代码 using System.Threading;namespace ClassLibrary1 {public class Class1{private Timer myTimer = null;//定义定时器用于触发事件//定义公共的委托和调…

短视频抖音seo矩阵系统源码开发者思路(一)

一套优秀的短视频获客系统&#xff0c;支持短视频智能剪辑、短视频定时发布&#xff0c;短视频排名查询及优化&#xff0c;短视频智能客服等&#xff0c;那么短视频seo系统具体开发应该具备哪些功能呢&#xff1f;今天小编就跟大家分享一下我们的技术开发思路。 抖音矩阵系统源…

Qt Https通信: TLS initialization failed 解决方法

Qt Https通信&#xff1a; TLS initialization failed 解决方法&#xff0c;Window端使用Qt 做开发请求Https资源时&#xff0c;会经常遇到 TLS initialization failed。 原因分析&#xff1a; 在Qt中并未包含 SSL所包含的库&#xff0c;因此需要开发者&#xff0c;自己将库拷贝…

百度iOS端长连接组件建设及应用实践

作者 | 百度消息中台团队 导读 在过去的十年里&#xff0c;移动端技术飞速发展&#xff0c;移动应用逐渐成为主要的便捷访问和使用互联网的方式&#xff0c;承接了越来越多的业务和功能&#xff0c;这也意味着对移动端和服务器之间的通信效率和稳定性提出了更高的要求。为了实现…

C语言实现简易通讯录

目录 普通版 功能需求 模块设计 test.c模块实现 contact.h模块实现 类型的声明 函数的声明 头文件、枚举、宏定义 contact.c 模块实现 初始化通讯录 增加联系人 显示所有联系人的信息 查找函数 删除指定联系人 查找指定联系人 修改指定联系人 进阶版通讯录&a…

基于scrcpy的Android群控项目重构,获取Android屏幕元素信息并编写自动化事件

系列文章目录 基于scrcpy的远程调试方案 基于scrcpy的Android群控项目重构 基于scrcpy的Android群控项目重构 进阶版 基于scrcpy的Android群控项目重构&#xff0c;获取Android屏幕元素信息并编写自动化事件&#xff08;视频&#xff09; 基于scrcpy的Android群控项目重构…

面向个人的免费组态软件:摩尔信使MThings

产品官网 现代工业自动化各行各业中均广泛应用工控上位机软件&#xff0c;但同时也面临着一系列挑战和复杂性。 多样化设备组网&#xff1a;工控系统包含不同厂家的各类硬件和设备&#xff0c;如传感器、执行器、PLC等。工控上位机软件需要与不同类型的设备进行集成和通信&am…

C++常用库函数 2.字符分类函数

函数名&#xff1a;isalnum 函数原型&#xff1a;int isalnum(int c)&#xff1b; 所需头文件&#xff1a;<cctype> 功能&#xff1a;测试 c 是否字母或数字。 返回值&#xff1a;如果 c 在 A&#xff5e;Z、a&#xff5e;z 或0&#xff5e;9的范围内&#xff0c;则返回…

[Linux] 最基础简单的线程池 及其 单例模式的实现

本篇文章主要用到线程相关内容, 下面是博主关于线程相关内容的文章: [Linux] 线程同步分析&#xff1a;什么是条件变量&#xff1f;生产者消费者模型是什么&#xff1f;POSIX信号量怎么用&#xff1f;阻塞队列和环形队列模拟生产者消费者模型 [Linux] 线程互斥分析: 多线程的问…

使用claude 2的文档分析功能

复制一段较长的文本内容&#xff0c;比如json文件。 https://zh.annas-archive.org/db/aarecord/md5:ba19176859126615bba9f35110f7492e.json 打开claude 2网页。 在输入框中粘贴内容&#xff0c;会自动生成一个past.txt图标。 输入要问的问题&#xff0c;按回车。 结果如下&a…