【Spring】Bean

Spring 将管理对象称为 BeanSpring 可以看作是一个大型工厂,用于生产和管理 Spring 容器中的 Bean。如果要使用 Spring 生产和管理 Bean,那么就需要将 Bean 配置在 Spring 的配置文件中。Spring 框架支持 XMLProperties 两种格式的配置文件,在实际开发中常用 XML 格式的配置文件。

Bean 的配置

通常,在 XML 文件中,根元素为 <beans><beans> 中包含多个 <bean> 子元素,每个 <bean> 定义一个 Bean,并描述 Bean 如何被装配到 Spring 容器中。

<beans>
    <bean/>
    <bean></bean>
</beans>
属性或子元素名称描述
idBeanBeanFactory 中的唯一标识,获取 Bean 实例时需要以此作为索引名称
classBean 的具体实现类,使用类名
scope指定 Bean 实例的作用域
nameBean 的别名,多个别名之间用逗号、空格或分号分隔
<constructor-arg><bean> 元素的子元素,使用构造方法注入,指定构造方法的参数。该元素的 index 属性指定参数的序号,ref属性指定对 BeanFactory 中其他 Bean的引用关系,type 属性指定参数类型,value 属性指定参数的常量值
<property><bean> 元素的子元素,用于设置一个属性。该元素的 name 属性指定 Bean 实例中相应的属性名称,value 属性指定 Bean 的属性值,ref 属性指定属性对 BeanFactory 中其他 Bean 的引用关系
<list><property> 元素的子元素,用于封装 List 或数组类型的依赖注入
<map><property> 元素的子元素,用于封装 Map 类型的依赖注入
<set><property> 元素的子元素,用于封装 Set 类型的依赖注入
<entry><map> 元素的子元素,用于设置一个键值对

Bean 的作用域

Spring 中可以为 Bean 指定作用域:
在这里插入图片描述

Bean 的实例化

Spring 框架中,如果想使用 Spring 容器中的 Bean,需要对其进行实例化。Spring 框架实例化 Bean 有3种方式,即构造方法实例化、静态工厂实例化和实例工厂实例化。

(1)构造方法实例化

Spring 框架中,Spring 容器可以调用 Bean 对应类的无参构造方式来实例化 Bean

public class BookDaoImpl implements BookDao {
    @Override
    public void save() {
    }
}
<bean id="bookDao" class="com.dao.impl.BookDaoImpl"/>

注意:若没有无参构造方法,则将抛出 BeanCreationException 异常

(2)静态工程实例化

在使用静态工厂实例化 Bean 时,开发者需要在工厂类中创建一个静态方法来创建 Bean 的实例。在配置 Bean 时,class 属性指定静态工厂类,同时还需要使用 factory-method 属性指定工厂类中的静态方法:

public class BookDaoImpl implements BookDao {
    @Override
    public void save() {
    }
}

// ...
public class BookDaoFactory {
    public static BookDao getBookDao() {
        return new BookDaoImpl();
    }
}
<bean id="bookDao" class="com.factory.BookDaoFactory" factory-method="getBookDao"/>

(3)实例工厂实例化

在使用实例工厂实例化 Bean 时需要我们在工厂类中创建一个实例方法来创建 Bean 的实例。在配置 Bean 时需要使用 factory-bean 属性指定配置的实例工厂,同时还需要使用 factory-method 属性指定实例工厂中的实例方法:

public class BookDaoImpl implements BookDao {
    @Override
    public void save() {
    }
}

// ...
public class BookDaoFactory {
    public BookDao getBookDao() {
        return new BookDaoImpl();
    }
}
<bean id="bookDaoFactory" class="com.factory.BookDaoFactory"/>
<bean id="bookDao" factory-method="getBookDao" factory-bean="bookDaoFactory"/>

除了上面的实现方式,还可以对实例工厂实例化方式进行简化,即使用 FactoryBean 实例化 Bean。创建一个实现 FactoryBean 接口的工厂方法,实现统一接口,最后进行配置:

public class BookDaoFactoryBean implements FactoryBean<BookDao> {
    @Override
    public BookDao getObject() throws Exception {
        return new BookDaoImpl();
    }
    @Override
    public Class<?> getObjectType() {
        return BookDao.class;
    }
    @Override
    public boolean isSingleton() {
        return true; // 使用单例模式
    }
}
<bean id="bookDao" class="com.factory.BookDaoFactoryBean"/>

Bean 的生命周期

Bean 的生命周期是指 Bean 从创建到消亡的完整过程。而 Bean 生命周期控制是指在 Bean 创建后到销毁前做一些事情。

public class BookDaoImpl implements BookDao {
    @Override
    public void save() {
    }
    // 用于实现 bean 初始后对应操作
    public void init() {
        System.out.println("init...");
    }
    // 用于实现 bean 销毁前对应操作
    public void destroy() {
        System.out.println("destroy...");
    }
}
<bean id="bookDao" class="com.dao.impl.BookDaoImpl" init-method="init" destroy-method="destroy"/>

上面是通过配置方法的方式实现 Bean 生命周期控制,也可以通过接口的方式实现 Bean 生命周期控制,实现 InitializingBeanDisposableBean 接口以及对应的方法:

public class BookDaoImpl implements BookDao, InitializingBean, DisposableBean {
    @Override
    public void save() {
    }
    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("init...");
    }
    @Override
    public void destroy() throws Exception {
        System.out.println("destroy...");
    }
}
<bean id="bookDao" class="com.dao.impl.BookDaoImpl"/>

我们运行 Bean 生命周期控制的代码会发现:init 执行了,但是 destroy 没有执行。原因是:程序运行在虚拟机中,在虚拟机启动后,会经历容器初始化、使用 Bean以及关闭/销毁容器三个阶段。然而,这里虚拟机并没有进入关闭/销毁容器阶段就退出了。这里有两种进入关闭/销毁阶段的方式:

(1)在虚拟机退出前,主动关闭容器

ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
ctx.close();

(2)注册关闭钩子

ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
ctx.registerShutdownHook(); // 指示在关闭虚拟机之前先关闭容器

Bean 的装配

Bean 的装配可以理解为将 Bean 依赖注入到 Spring 容器中。Spring 容器支持基于 XML 配置的装配、基于注解的装配以及自动装配等多种装配方式。

(1)基于 XML 配置的装配

Spring 中,有两种主要的基于 XML 配置的装配方式:一种是通过属性的 setter 方法进行注入,另一种是通过构造方法进行注入。根据注入的数据类型,这些方式又可以分为引用类型注入和简单类型注入。

  • 使用 setter 方法注入简单类型数据

bean 中定义简单类型数据并提供可访问的 set 方法:

public class BookDaoImpl implements BookDao {
    private int connectionNum;
    private String databaseName;
    public void setConnectionNum(int connectionNum) {
        this.connectionNum = connectionNum;
    }
    public void setDatabaseName(String databaseName) {
        this.databaseName = databaseName;
    }
}

配置中使用 property 标签 value 属性注入简单类型数据:

<bean id="bookDao" class="com.dao.impl.BookDaoImpl">
    <property name="connectionNum" value="10"/>
    <property name="databaseName" value="mysql"/>
</bean>
  • 使用 setter 方法注入引用类型数据

bean 中定义引用类型属性并提供可访问的 set 方法:

public class BookServiceImpl implements BookService {
    private BookDao bookDao;

    public void setBookDao(BookDao bookDao) {
        this.bookDao = bookDao;
    }
}

配置中使用 property 标签 ref 属性注入引用类型:

<bean id="bookService" class="com.service.impl.BookServiceImpl">
    <property name="bookDao" ref="bookDao"/>
</bean>
<bean id="bookDao" class="com.dao.impl.BookDaoImpl"/>
  • 使用构造方法注入简单类型数据

bean 中定义简单类型属性并提供可访问的构造方法:

public class BookDaoImpl implements BookDao {
    private int connectionNum;
    private String databaseName;
    public BookDaoImpl(int connectionNum, String databaseName) {
        this.connectionNum = connectionNum;
        this.databaseName = databaseName;
    }
}

配置中使用 constructor-arg 标签 value 属性注入简单类型对象:

<bean id="bookDao" class="com.dao.impl.BookDaoImpl">
    <constructor-arg name="connectionNum" value="10"/>
    <constructor-arg name="databaseName" value="mysql"/>
</bean>
  • 使用构造方法注入引用类型数据

bean 中定义引用类型属性并提供可访问的构造方法:

public class BookServiceImpl implements BookService {
    private BookDao bookDao;
    public BookServiceImpl(BookDao bookDao) {
        this.bookDao = bookDao;
    }
}

配置中使用 constructor-arg 标签 ref 属性注入引用类型对象:

<bean id="bookDao" class="com.dao.impl.BookDaoImpl"/>
<bean id="bookService" class="com.service.impl.BookServiceImpl">
    <constructor-arg name="bookDao" ref="bookDao"/>
</bean>

(2)基于注解的装配

使用 @Component 定义 bean

@Component("bookDao") // 起名称为 bookDao
public class BookDaoImpl implements BookDao {
    @Override
    public void save() {
    }
}

核心配置文件中通过组件扫描加载 bean

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

另外,Spring 提供了 @Component 注解的三个衍生注解,分别是:

  • @Controller:用于表现层 bean 定义
  • @Service:用于业务层 bean 定义
  • @Repository:用于数据层 bean 定义

(3)自动装配

IoC 容器根据 bean 所依赖的资源在容器中自动查找并注入到 bean 中的过程称为自动装配。自动装配的方式可分为:按类型、按名称、按构造方法和默认。

  • 配置中使用 bean 标签 autowire 属性设置自动装配的类型:
<bean id="bookDao" class="com.dao.impl.BookDaoImpl"/>
<bean id="bookService" class="com.service.impl.BookServiceImpl" autowire="byType"/>

使用细节

  • 自动装配用于引用类型依赖注入,不能对简单类型进行操作
  • 使用按类型装配时(byType)必须保障容器中相同类型的 bean 唯一,推荐使用
  • 使用按名称装配时(byName)必须保障容器中具有指定名称的 bean,因变量名与配置耦合,不推荐使用
  • 自动装配优先级低于 setter 注入与构造器注入,同时出现时自动装配配置失效

(4)集合的注入

public class BookDaoImpl implements BookDao {
    private int[] array;
    private List<String> list;
    private Set<String> set;
    private Map<String, String> map;
    private Properties properties;

    public void setArray(int[] array) {
        this.array = array;
    }
    public void setList(List<String> list) {
        this.list = list;
    }
    public void setSet(Set<String> set) {
        this.set = set;
    }
    public void setMap(Map<String, String> map) {
        this.map = map;
    }
    public void setProperties(Properties properties) {
        this.properties = properties;
    }
}
<bean id="bookDao" class="com.dao.impl.BookDaoImpl">
    <property name="array">
        <array>
            <value>100</value>
            <value>200</value>
        </array>
    </property>
    <property name="list">
        <list>
            <value>java se</value>
            <value>java ee</value>
        </list>
    </property>
    <property name="set">
        <set>
            <value>java se</value>
            <value>java ee</value>
        </set>
    </property>
    <property name="map">
        <map>
            <entry key="k1" value="v1"/>
            <entry key="k2" value="v2"/>
        </map>
    </property>
    <property name="properties">
        <props>
            <prop key="k1">v1</prop>
            <prop key="k2">v2</prop>
        </props>
    </property>
</bean>

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

[Python学习日记-68] 绑定方法与非绑定方法

[Python学习日记-68] 绑定方法与非绑定方法 简介 绑定方法 非绑定方法 绑定方法与非绑定方法的应用 简介 在之前我们学习类与对象的属性查找与绑定方法的时候就接触过绑定方法了&#xff0c;不过当时是简单的介绍了针对于对象的绑定方法&#xff0c;其实在类内部定义的函数…

逆向攻防世界CTF系列39-debug

逆向攻防世界CTF系列39-debug 查了资料说.NET要用其它调试器&#xff0c;下载了ILSPY和dnSPY ILSPY比较适合静态分析代码最好了&#xff0c;函数名虽然可能乱码不显示&#xff0c;但是单击函数名还是能跟踪的&#xff0c;而dnSPY在动态调试上效果好&#xff0c;它的函数名不仅…

Spring-事务学习

spring事务 1. 什么是事务? 事务其实是一个并发控制单位&#xff0c;是用户定义的一个操作序列&#xff0c;这些操作要么全部完成&#xff0c;要不全部不完成&#xff0c;是一个不可分割的工作单位。事务有 ACID 四个特性&#xff0c;即&#xff1a; 原子性&#xff08;Atom…

RHCE的学习(21)

第三章 Shell条件测试 用途 为了能够正确处理Shell程序运行过程中遇到的各种情况&#xff0c;Linux Shell提供了一组测试运算符。 通过这些运算符&#xff0c;Shell程序能够判断某种或者几个条件是否成立。 条件测试在各种流程控制语句&#xff0c;例如判断语句和循环语句中…

用pyspark把kafka主题数据经过etl导入另一个主题中的有关报错

首先看一下我们的示例代码 import os from pyspark.sql import SparkSession import pyspark.sql.functions as F """ ------------------------------------------Description : TODO&#xff1a;SourceFile : etl_stream_kafkaAuthor : zxxDate : 2024/11/…

单片机_day3_GPIO

目录 1. 灯如何才能亮 1.1原理图 1.2 二极管 1.3 换了一个灯和原理图 ​编辑 1.4 三极管 1.4.1 NPN型三极管 1.4.2 PNP型三极管 2. 基本概念 3. 输入 3.1 浮空输入 3.2 上拉输入 3.3 下拉输入 3.4 模拟输入 4. 输出 4.1 推挽输出 4.2 开漏输出 如何让开漏输出…

基于视觉智能的时间序列基础模型

GitHub链接&#xff1a;ViTime: A Visual Intelligence-Based Foundation Model for Time Series Forecasting 论文链接&#xff1a;https://github.com/IkeYang/ViTime 前言 作者是来自西安理工大学&#xff0c;西北工业大学&#xff0c;以色列理工大学以及香港城市大学的研…

java项目-jenkins任务的创建和执行

参考内容: jenkins的安装部署以及全局配置 1.编译任务的general 2.源码管理 3.构建里编译打包然后copy复制jar包到运行服务器的路径 clean install -DskipTests -Pdev 中的-Pdev这个参数用于激活 Maven 项目中的特定构建配置&#xff08;Profile&#xff09; 在 pom.xml 文件…

Qt按钮类-->day09

按钮基类 QAbstractButton 标题与图标 // 参数text的内容显示到按钮上 void QAbstractButton::setText(const QString &text); // 得到按钮上显示的文本内容, 函数的返回就是 QString QAbstractButton::text() const;// 得到按钮设置的图标 QIcon icon() const; // 给按钮…

论文6—《基于YOLOv5s的深度学习在自然场景苹果花朵检测中的应用》文献阅读分析报告

论文报告&#xff1a;基于YOLOv5s的深度学习在自然场景苹果花朵检测中的应用 基于YOLOv5s的深度学习在自然场景苹果花朵检测中的应用 摘要国内外研究现状1. 疏花技术研究2. 目标检测算法研究 研究目的研究问题使用的研究方法试验研究结果文献结论创新点和对现有研究的贡献1. Y…

「人眼视觉不再是视频消费的唯一形式」丨智能编解码和 AI 视频生成专场回顾@RTE2024

你是否想过&#xff0c;未来你看到的电影预告片、广告&#xff0c;甚至新闻报道&#xff0c;都可能完全由 AI 生成&#xff1f; 在人工智能迅猛发展的今天&#xff0c;视频技术正经历着一场前所未有的变革。从智能编解码到虚拟数字人&#xff0c;再到 AI 驱动的视频生成&#…

计算机毕业设计Python美食推荐系统 美团爬虫 美食可视化 机器学习 深度学习 混合神经网络推荐算法 Hadoop Spark 人工智能 大数据毕业设计

温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 作者简介&#xff1a;Java领…

GPU分布式通信技术-PCle、NVLink、NVSwitch深度解析

GPU分布式通信技术-PCle、NVLink、NVSwitch 大模型时代已到来&#xff0c;成为AI核心驱动力。然而&#xff0c;训练大模型却面临巨大挑战&#xff1a;庞大的GPU资源需求和漫长的学习过程。 要实现跨多个 GPU 的模型训练&#xff0c;需要使用分布式通信和 NVLink。此外&#xf…

MySQL:联合查询(2)

首先写一个三个表的联合查询 查询所有同学的每门课成绩&#xff0c;及同学的个人信息 1.我们首先要确定使用哪些表 学生表&#xff0c;课程表&#xff0c;成绩表 2.取笛卡尔积 select * from score,student,course; 3. 确定表与表之间的联合条件 select * from score,stud…

【leetcode】704. 二分查找

注意一般mid left (right-left)/2; 不要用mid (right - left)/2 中间值的计算需要考虑到整型溢出的问题。 如果使用 mid (right - left) / 2 的方式计算中间值&#xff0c;那么在 right 和 left 的值接近极限值的情况下&#xff0c;可能会导致计算出的中间值发生整型溢出&…

RHCE的练习(12)

写一个脚本&#xff0c;完成以下要求&#xff1a; 给定一个用户&#xff1a; 如果其UID为0&#xff0c;就显示此为管理员&#xff1b;否则&#xff0c;就显示其为普通用户&#xff1b; #!/bin/bash ​ # 使用read命令获取用户名 read -p "请输入用户名: " username ​…

WPF-控件的属性值的类型转化

控件的属性值需要转成int、double进行运算的&#xff0c;可以使用一下方法 页面代码 <StackPanel Margin"4,0,0,0" Style"{StaticResource Form-StackPanel}"> <Label Content"替换后材料增加金额&#xff…

【从零开始的LeetCode-算法】3270. 求出数字答案

给你三个 正 整数 num1 &#xff0c;num2 和 num3 。 数字 num1 &#xff0c;num2 和 num3 的数字答案 key 是一个四位数&#xff0c;定义如下&#xff1a; 一开始&#xff0c;如果有数字 少于 四位数&#xff0c;给它补 前导 0 。答案 key 的第 i 个数位&#xff08;1 < …

iMetaOmics | 刘永鑫/陈同-用于食物微生物组成和时间序列研究的微生物组数据库FoodMicroDB...

点击蓝字 关注我们 FoodMicroDB&#xff1a;用于食物微生物组成和时间序列研究的微生物组数据库 iMeta主页&#xff1a;http://www.imeta.science 研究论文 ● 原文链接DOI: https://doi.org/10.1002/imo2.40 ● 2024年11月1日&#xff0c;中国农业科学院深圳农业基因组研究所刘…

视觉slam十四讲 ch8 光流法和直接法

之前的都是单层光流 转载至Blibli 视觉SLAM十四讲_7视觉里程计1_计算相机运动_哔哩哔哩_bilibili