Java学习 - spring Bean 详解

news2024/12/23 18:38:02

Bean 的别名配置

接着上一篇文章中的 <bean> 配置,其中配置了 id 属性,通过 id 属性我们就可以获取到对象。其实 <bean> 配置也提供了 name 属性,它是用于定义 Bean 的别名,一个 Bean 的别名是可以有多个的,各个别名之间可以通过逗号(,)、分号(;)、空格( )分隔。

<!--  配置 bean  -->
<bean id="bookDao" name="dao bookDaoImpl" class="com.cunyu.dao.impl.BookDaoImpl"/>
<bean id="bookService" name="service,bookServiceImpl" class="com.cunyu.service.impl.BookServiceImpl">
    <!-- property 表示配置当前 Bean 的属性
             name 表示配置哪一个具体的属性
             ref 表示参照的 Bean
             -->
    <property name="bookDao" ref="bookDao"/>
</bean>

当我们要获取 Bean 时,既可以通过 id,也可以通过 name 获取。两者的区别在于 id 属性是惟一的,而 name 不是,因此在配置时,更加推荐使用 id 而非 name 防止因为重名而导致在获取 Bean 时混淆。

通过 id 或者 name 获取 Bean 时,如果获取不到,此时程序将抛出异常 NoSuchBeanDefinitionException

NoSuchBeanDefinitionException: No bean named 'xxx' available

一旦遇到以上错误,那么第一反应应该是是去 Spring 配置文件 applicationContext.xml 中查看对应 Bean 是否配置,或者在代码和配置中的 Bean 名是否匹配一致。

Bean 的作用范围

Bean 既然是一个对象,那么它也是有作用范围的。在 <bean> 配置时我们可以利用 scope 属性。

说明
singleton单例,也是 Bean 磨人的作用范围
prototype非单例
<bean id="bookService" class="com.cunyu.service.impl.BookServiceImpl" />
<bean id="bookService" class="com.cunyu.service.impl.BookServiceImpl" scope="singleton"/>

以上两种配置的效果是一致的,因为 Bean 默认的作用范围是 singleton。接着我们创建两个 BookService 对象,然后打印出来,可以看到它们指向的是同一块内存。

public class AppIoC {
    public static void main(String[] args) {
        //    加载配置文件,获取 IoC 容器
        ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");

        BookService bookService1 = (BookService) app.getBean("bookService");
        BookService bookService2 = (BookService) app.getBean("bookService");
        System.out.println(bookService1);
        System.out.println(bookService2);
    }
}

在这里插入图片描述

而如果我们将 Bean 的 scope 配置为 prototype,那么此时再创建两个 BookService 对象,然后对比它们的内存地址,会发现两者指向的并非指向同一块内存。

<bean id="bookService" class="com.cunyu.service.impl.BookServiceImpl" scope="prototype"/>
public class AppIoC {
    public static void main(String[] args) {
        //    加载配置文件,获取 IoC 容器
        ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");

        BookService bookService1 = (BookService) app.getBean("bookService");
        BookService bookService2 = (BookService) app.getBean("bookService");
        System.out.println(bookService1);
        System.out.println(bookService2);
    }
}

在这里插入图片描述

Bean 实例化

构造方法

Bean 的本质是对象,所以可以使用构造方法完成。

同样基于上一篇文章中的实例,配置好 <bean> 之后,然后在 BookDao 接口的实现中用构造方法来创建 Bean,最后在主程序入口中获取 Bean 之后调用方法,可以发现调用了构造方法。

<bean id="bookDao" class="com.cunyu.dao.impl.BookDaoImpl"/>
public class BookDaoImpl implements BookDao {
    private BookDaoImpl() {
        System.out.println("构造方法");
    }

    @Override
    public void save() {
        System.out.println("book dao save ……");
    }
}
public class AppIoC {
    public static void main(String[] args) {
        //    加载配置文件,获取 IoC 容器
        ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
        //    获取 Bean
        BookDao bookDao = (BookDao) app.getBean("bookDao");
        bookDao.save();
    }
}


在这里插入图片描述

静态工厂方法

利用静态工厂方法对 Bean 进行实例化时,首先需要创建一个工厂类,并在工厂类中创建一个静态方法用于创建对象。然后在 Spring 的配置文件 applicationContext.xml 中配置静态工厂类并指定其中的方法,最后在主程序入口中获取 Bean 并调用方法即可。

public class BookDaoFactory {
    public static BookDao getBookDao() {
        return new BookDaoImpl();
    }
}
<bean id="bookDao" factory-method="getBookDao" class="com.cunyu.factory.BookDaoFactory"/>
public class AppIoC {
    public static void main(String[] args) {
        //    加载配置文件,获取 IoC 容器
        ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
        //    获取 Bean
        BookDao bookDao = (BookDao) app.getBean("bookDao");
        bookDao.save();
    }
}

在这里插入图片描述

实例工厂对象方法

假设有一个接口和它的实现如下:

public interface PersonDao {
    public void query();
}
public class PersonDaoImpl implements PersonDao {
    @Override
    public void query() {
        System.out.println("Person Dao query……");
    }
}

我们创建一个实例工厂方法,注意此时我们是继承了 FactoryBean 接口,然后实现了其中的 getObject()getObjectType() 两个方法。

public class PersonDaoFactoryBean implements FactoryBean<PersonDao> {
    @Override
    public PersonDao getObject() throws Exception {
        return new PersonDaoImpl();
    }

    @Override
    public Class<?> getObjectType() {
        return PersonDao.class;
    }
}

接着在 Spring 的配置文件中进行配置,需要注意此时的类应该是我们的工厂类 PersonDaoFactoryBean,而不是 PersonDaoImpl

<bean id="personDao" class="com.cunyu.factory.PersonDaoFactoryBean"/>

最后在程序主入口中获取 Bean,然后调用方法即可。

public class AppIoC {
    public static void main(String[] args) {
        //    加载配置文件,获取 IoC 容器
        ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
        //    获取 Bean
        PersonDao personDao = (PersonDao) app.getBean("personDao");
        personDao.query();
    }
}

在这里插入图片描述

Bean 的生命周期

先来看看生命周期的定义,所谓生命周期就是指从创建到消亡的完整过程,类比到我们人身上,生命周期就是从我们出生到死亡的这个过程。而 Bean 的生命周期就指的是 Bean 从创建到销毁的整体过程。

Bean 的生命周期主要分为三个阶段:

  • 初始化容器
  • 使用 Bean
  • 销毁容器

初始化容器阶段,主要执行的操作有:创建对象(内存分配)、执行构造方法、执行属性注入(set 操作)、执行 Bean 初始化方法。

使用 Bean 阶段,主要是去执行业务操作。

销毁容器阶段,主要是执行 Bean 的销毁方法。

总结

以上就是今天关于 Bean 的内容了,主要从 Bean 的别名配置、作用范围、如何进行实例化以及声明周期 4 个方面着手,学习了 Bean 的相关操作。

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

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

相关文章

[C++]——同步异步日志系统(7)

同步异步日志系统 一、日志器管理模块&#xff08;单例模式&#xff09;1.1 对日志器管理器进行设计1.2 实现日志器管理类的各个功能1.3. 设计一个全局的日志器建造者1.4 测试日志器管理器的接口和全局建造者类 二、宏函数和全局接口设计2.1 新建一个.h,文件,文件里面放我们写的…

视图库对接系列(GA-T 1400)十九、视图库对接系列(级联)注册

背景 在上一章视图库对接系列(GA-T 1400)十八、视图库对接系列(级联)代码生成中我们已经把代码生成了,那怎么实现级联? 我们可以抓包看设备是怎么注册到我们平台的, 那我们就怎么实现就可以了。 实现 先看设备注册到我们服务端的包 步骤 注册我们可以参考视图库对接系列(…

Data类中的常用方法

Calender类 java.util.Calendar是一个抽象的基类&#xff0c;创建对象需要使用静态方法Calendar.getInstance()完成。通过Calendar对象可以获得详细的日历信息&#xff0c;例如年、月、日、小时、分和秒&#xff0c;Calendar的子类可以实现特定的日历系统。 当前时间 Calenda…

CV每日论文--2024.7.16

1、Radiance Fields from Photons 中文标题&#xff1a;光子的辐射场 简介&#xff1a;神经辐射场(NeRFs)已成为从多个视角捕获的图像进行高质量视图合成的事实标准方法。然而,在野外环境下捕获图像时,仍存在许多挑战,例如低光、高动态范围或快速运动导致的模糊重建和明显的伪…

【MySQL进阶篇】索引

1、索引概述 索引&#xff08;Index&#xff09;是帮助MySQL高效获取数据的数据结构&#xff08;有序&#xff09;。在数据之外&#xff0c;数据库系统还维护着满足特定查找算法的数据结构&#xff0c;这些数据结构以某种方式引用&#xff08;指向&#xff09;数据&#xff0c…

高职院校专业群的生成机制研究

摘要&#xff1a;本研究针对我国产业转型升级背景下高职院校专业群的生成机制进行了深入探讨。运用案例分析法&#xff0c;从生成决策、生成目标、生成规则三个维度出发&#xff0c;对专业群的生成机制进行了系统分析。研究发现&#xff0c;高职院校专业群的生成是一个与产业环…

容器之Harbor

Harbor 是一个开源的企业级 Docker 镜像仓库&#xff0c;用于存储、签名和扫描 Docker 镜像。它由 VMware 开发&#xff0c;旨在增强用户在容器化环境中的安全性和效率。以下是对 Harbor 的详细介绍&#xff1a; 主要功能 1. 镜像管理 镜像存储&#xff1a;提供高效的存储管理…

誉天教育与武汉晴川学院携手开展鸿蒙实训营,共筑鸿蒙生态新篇章!

在数字经济蓬勃发展的今天&#xff0c;鸿蒙系统作为华为自主研发的操作系统&#xff0c;正逐步构建起一个开放、协同、共赢的生态体系。为了进一步推动鸿蒙生态的繁荣发展&#xff0c;培养更多具备鸿蒙原生应用开发能力的专业人才&#xff0c;誉天教育与武汉晴川学院强强联合&a…

苹果公司等科技巨头涉嫌违规使用 YouTube 视频训练 AI|TodayAI

YouTube 强调&#xff0c;使用其平台内容训练人工智能违反服务条款&#xff0c;苹果公司&#xff08;Apple&#xff09;、Anthropic 等科技巨头却涉嫌违规 根据 Proof News 和 Wired 合作的一项调查报告&#xff0c;超过 17 万个 YouTube 视频成为了苹果公司、Anthropic、Nvid…

2024年大数据高频面试题(中篇)

文章目录 Kafka为什么要用消息队列为什么选择了kafkakafka的组件与作用(架构)kafka为什么要分区Kafka生产者分区策略kafka的数据可靠性怎么保证ack应答机制(可问:造成数据重复和丢失的相关问题)副本数据同步策略ISRkafka的副本机制kafka的消费分区分配策略Range分区分配策略…

单链表算法 - 环形链表I

. - 力扣&#xff08;LeetCode&#xff09;. - 备战技术面试&#xff1f;力扣提供海量技术面试资源&#xff0c;帮助你高效提升编程技能,轻松拿下世界 IT 名企 Dream Offer。https://leetcode.cn/problems/linked-list-cycle/description/思路: 代码: /*** Definition for sin…

Docker的数据管理和网络通信

目录 一、Docker 的数据管理 1&#xff0e;数据卷 2&#xff0e;数据卷容器 二、端口映射 三、容器互联&#xff08;使用centos镜像&#xff09; 四、*Docker 镜像的创建 1&#xff0e;基于现有镜像创建 2&#xff0e;基于本地模板创建 3&#xff0e;基于Dockerfile 创…

第二十章 Nest 大文件分片上传

在前端的文件上传功能中&#xff0c;只要请求头里定义 content-type 为 multipart/form-data&#xff0c;内容就会以下面形式传递到服务端&#xff0c;接着服务器再按照multipart/form-data的格式去提取数据 获取文件数据但是当文件体积很大时 就会出现一个问题 文件越大 请求的…

cpp 强制转换

一、static_cast static_cast 是 C 中的一个类型转换操作符&#xff0c;用于在类的层次结构中进行安全的向上转换&#xff08;从派生类到基类&#xff09;或进行不需要运行时类型检查的转换。它主要用于基本数据类型之间的转换、对象指针或引用的向上转换&#xff08;即从派生…

Mysql缓存调优的基本知识(附Demo)

目录 前言1. 配置2. 缓存3. 策略 前言 基本的知识推荐阅读&#xff1a; java框架 零基础从入门到精通的学习路线 附开源项目面经等&#xff08;超全&#xff09;Mysql优化高级篇&#xff08;全&#xff09;Mysql底层原理详细剖析常见面试题&#xff08;全&#xff09; MySQL…

【网络安全的神秘世界】HackBar绕过许可证

&#x1f31d;博客主页&#xff1a;泥菩萨 &#x1f496;专栏&#xff1a;Linux探索之旅 | 网络安全的神秘世界 | 专接本 | 每天学会一个渗透测试工具 &#x1f344;问题描述 用Firefox浏览器安装hackbar插件后&#xff0c;按F12键&#xff0c;发现如下提示&#xff1a;无法使…

防火墙的带宽管理

一、实验拓扑 目录 一、实验拓扑 二、实验要求 三、实验步骤 3.1将防火墙组网改成双机热备的组网形式&#xff0c;做负载分担模式&#xff0c;游客区和DMZ区走FW3&#xff0c;生产区和办公区的流量走FW1 3.1.1心跳线设置 3.2启用双机热备&#xff0c;并配置VRRP组 3.2.1…

MySQL常用命令的实战应用

MySQL常用命令全攻略&#xff1a;从入门到精通的实用指南 在数字化时代的浪潮中&#xff0c;MySQL作为关系型数据库管理系统的佼佼者&#xff0c;以其稳定性和高效性赢得了全球用户的青睐。无论是新手还是资深开发者&#xff0c;掌握MySQL的常用命令都是提升数据库管理能力的基…

内行人才知道的白酒术语

&#x1f61c;宝子们&#xff0c;今天来给大家分享一些只有内行人懂的白酒术语&#xff0c;让你在酒桌上也能显得很专业&#xff01;&#x1f4aa; ⬆️基酒术语解释&#xff1a;所谓基酒就是最基础的酒&#xff0c;也叫原浆酒&#xff0c;是指成酒后不经过勾调的酒液。基酒度…

数据库内核研发学习之路(三)创建postgres内置函数

本章之前已经讲明白了我们的postgres如何进行编译安装&#xff0c;这是很重要的一步&#xff0c;接下来就是学会对postgres进行小的改动&#xff0c;然后保证依然能够顺利编译安装运行&#xff01; 本章续讲内容如何创建一个内置函数。 1、内置函数和用户自定义函数的区别 熟…