Spring Bean自动装配:深入解析与实战应用

news2024/10/7 8:20:13

 

 

何为自动装配

在使用Spring框架配置bean时,我们通常需要为bean的属性设置值。如果不手动设置这些值,它们通常会被初始化为默认值(对于对象类型通常是null,对于基本类型如int则是0,boolean是false等)。自动装配的好处在于,我们不需要手动为每个依赖的bean设置值,Spring容器会根据配置在上下文中自动寻找并装配合适的值。

在Spring中,有几种不同的装配方式:

  1. XML配置:
    通过Spring的XML配置文件,我们可以显式地定义bean以及它们之间的依赖关系。这通常涉及使用<bean>标签来定义bean,并通过<property><constructor-arg>标签来设置bean的属性或构造器参数。

  2. Java配置(或称为注解配置):
    从Spring 3.0开始,我们可以使用Java类来定义bean和它们之间的依赖关系,而不是使用XML。这通常涉及使用@Configuration注解来标记一个类作为配置类,并使用@Bean注解来标记一个方法作为bean的工厂方法。

  3. 自动装配:
    Spring提供了自动装配功能,可以自动解析和注入bean之间的依赖关系。这可以通过在bean上使用@Autowired@Resource@Inject等注解来实现。这些注解告诉Spring容器在创建bean时自动查找并注入所需的依赖项。

    • @Autowired:Spring特有的注解,用于自动装配bean。默认情况下,它按类型(byType)自动装配。当存在多个相同类型的bean时,可以使用@Qualifier注解来指定要注入的bean的名称。

    • @Resource:Java EE的注解,也支持自动装配。与@Autowired不同,@Resource默认按名称(byName)查找bean,但也可以按类型查找(如果同时指定了名称和类型)。

    • @Inject:这是JSR-330规范的一部分,与@Autowired类似,但它是Java标准的一部分,不仅限于Spring。

 

环境准备

先来定义好三个 POJO 类,Teacher、Student、Study。并且有一个关系就是 Teacher拥有学生和学科。

package com.JavaClass.pojo;

public class student{
    public void shout(){
        System.out.println("我是学生");
    }
}
package com.JavaClass.pojo;

public class study {
    public void shout(){
        System.out.println("I like study");
    }
}
package com.JavaClass.pojo;


public class teacter{


    private Student student;
    private Study study;
    private String name;
    /* getter/setter 和 toString */

}

Spring 配置文件部分:

在该项目的resources目录下,创建一个spring-config.xml 用来配置文件spring-config.xml文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd">

<bean id="student" class="com.JavaClass.pojo.Student"/>
<bean id="study" class="com.JavaClass.pojo.Study"/>
<bean id="teacher" class="com.JavaClass.pojo.Teacher">
    <property name="name" value="JAVA学习课堂/>
        <property name="cat" ref="cat"/>
        <property name="dog" ref="dog"/>
    </bean>
</beans>

在该项目的src/test/java目录下,创建一个MyTest测试类,用来测试代码。

import com.JavaClass.pojo.Teacher;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class MyTest {
    @Test
    public void test(){
        //解析beans.xml文件,IOC容器生成并管理相应的Bean对象
        ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");

        //通过Spring的上下文对象,从IOC容器中获取Bean对象
        Teacher person = context.getBean("teacher", Teacher.class);
        //调用Bean对象的方法
        person.getStudent().shout();
        person.getStudy().shout();
    }
}

 

测试默认装配的结果如图:

 

e2284df81442845c4d0f72e311b2953c.png

配置实现自动装配

自动装配在Spring中有几种不同的方式,主要包括:

  1. byName:
    根据属性名自动装配。Spring容器会查找与bean的属性名相同的另一个bean的定义,并将其自动装配到当前bean中。

  2. byType:
    根据属性类型自动装配。Spring容器会查找与bean的属性的类型相匹配的bean定义,如果有多个相同类型的bean,则会抛出异常,除非指定了其他方式(如使用@Qualifier注解)来消除歧义。

  3. constructor:
    基于构造函数的自动装配。与基于类型的自动装配类似,但它是应用于构造函数的参数。Spring容器会查找与构造函数的参数类型相匹配的bean定义,并使用这些bean来实例化当前的bean。

byName

在使用Spring框架的自动装配特性时,若启用了byName模式,则容器会按照特定规则查找与bean属性匹配的bean定义。具体而言,它会根据类中定义的setter方法名(去掉set前缀,并将剩余部分的首字母转换为小写)来寻找一个具有相同ID的bean定义。例如,如果 theacher 类中包含一个名为setStudent的setter方法,并且Spring的配置文件中存在一个ID为student的bean定义,那么Spring容器在启用byName自动装配后,会自动将ID为student的bean注入到Teacher类的student属性中。

 

操作:修改  spring-config.xml  文件中的代码:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="student" class="com.JavaClass.pojo.Student"/>
    <bean id="study" class="com.JavaClass.pojo.Study"/>

    <!--加上了 person 的 bean 的 autowired 属性
    并去掉了手动装配的 cat 和 dog -->
    <bean id="teacher" class="com.JavaClass.pojo.Teacher" autowire="byName">
        <property name="name" value="Java学习课堂"/>
    </bean>
    <!--    <bean id="person" class="com.JavaClass.pojo.Person">-->
    <!--        <property name="name" value="Java学习课堂"/>-->
    <!--        <property name="cat" ref="cat"/>-->
    <!--        <property name="dog" ref="dog"/>-->
    <!--    </bean>-->
</beans>
 

结果依旧相同,证明这样根据 byName 的代码是没问题的。

 

9423d3f7181b526677df1d73c05417b8.png

byType

byType模式会根据bean中所需依赖的类型,在容器上下文中自动寻找匹配的bean定义并进行装配。如果容器中存在一个或多个与所需依赖类型相匹配的bean,Spring将尝试将它们自动注入到当前bean中。

改动下 spring-config.xml 配置文件中 id 为 teacher  的 bean,配置成byType 模式

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="student" class="com.JavaClass.pojo.Student"/>
    <bean id="study" class="com.JavaClass.pojo.Study"/>

    <!--加上了 person 的 bean 的 autowired 属性
    并去掉了手动装配的 cat 和 dog -->
    <bean id="teacher" class="com.JavaClass.pojo.Teacher" autowire="byType">
        <property name="name" value="Java学习课堂"/>
    </bean>
</beans>
 

注:byType自动装配时,存在一个潜在的问题,即当容器中存在多个相同类型的bean时,由于不是基于唯一的id来匹配,而是根据类型进行匹配,Spring将无法确定应该注入哪一个bean,这会导致一个异常。

 

afb010a05fa44102dc016e4e4ba8121d.png

 

8887a9dc647bba56f74dc6d4ef829bc1.png

 

使用注解实现自动装配

使用注解的准备

如果使用注解我们还需要对原本的配置文件做一些修改,增加约束,来支持通过注解的形式实现自动装配。

<?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:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        https://www.springframework.org/schema/context/spring-context.xsd">

    <!-- 开启注解支持 -->
    <context:annotation-config/>

    <bean id="student" class="com.JavaClass.pojo.Student"/>
    <bean id="study" class="com.JavaClass.pojo.Study"/>
    <bean id="teacher" class="com.JavaClass.pojo.Teacher"/>

</beans>

@AutoWired注解的使用

在 POJO 类需要自动装配的属性上加 @AutoWired 注解实现自动装配。

package com.JavaClass.pojo;

import org.springframework.beans.factory.annotation.Autowired;

public class Teacher {

    @Autowired
    private Student student;
    @Autowired
    private Study study;
    private String name;

    /* getter/setter 和 toString */

}

执行测试代码,结果如下:

 

9423d3f7181b526677df1d73c05417b8.png

@Qualifier

当在Spring配置中定义了同一个类的多个bean,并使用@Autowired注解进行自动装配时,由于@Autowired默认采用按类型(byType)的装配方式,Spring框架将无法直接确定应该注入哪一个bean实例,因为存在多个相同类型的候选者。

可以使用@Qualifier注解:通过在@Autowired注解旁边添加@Qualifier注解,可以指定要注入的bean的名称。例如,如果有一个名为myBeanA和myBeanB的相同类型的bean,你可以在@Autowired注解旁边使用@Qualifier("myBeanA")来指定注入myBeanA。

 

测试:在配置文件中增加一个 Student 的 bean。

<?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:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        https://www.springframework.org/schema/context/spring-context.xsd">

    <!-- 开启注解支持 -->
    <context:annotation-config/>

    <bean id="student" class="com.JavaClass.pojo.Student"/>
    <bean id="student2" class="com.JavaClass.pojo.Student"/>
    <bean id="study" class="com.JavaClass.pojo.Study"/>
    <bean id="teacher" class="com.JavaClass.pojo.Teacher"/>

</beans>

Teacher 类中配合 @Qualifier  注解

package com.JavaClass.pojo;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;

public class Teacher{

    @Autowired
    @Qualifier("student")
    private Student student;
    @Autowired
    private Study study;
    private String name;

/* getter/setter 和 toString */
}

测试代码结果如下“

 

9423d3f7181b526677df1d73c05417b8.png

@Resource

在Spring框架中,@Resource注解用于自动装配bean,它结合了@Autowired(按类型装配)和@Qualifier(按名称装配)的功能。在bean的自动装配过程中,可以使用@Resource注解的name属性来指定要注入的bean的名称,这个name属性的作用类似于@Qualifier注解的value属性,用于消除类型相同的bean之间的歧义。同时,@Resource还提供了额外的功能,如根据JNDI名称查找资源。

@Resource 与 @AutoWired 的不同在于:

  • @Resource 默认是按照 名称 来装配注入的,当找不到与名称匹配的 bean 才会按照类型来装配注入。

  • @Autowired 默认是按照 类型 装配注入的,如果想按照名称来装配注入,则需要结合 @Qualifier 一起使用;

 

通过 @Resource 注解来进行自动装配 bean

import javax.annotation.Resource;

public class Teacher{

    @Resource
    private Student student;
    @Resource
    private Study study;
    private String name;

    /* getter/setter 和 toString */

 

<bean id="student1" class="com.JavaClass.pojo.Student"/>
<bean id="student2" class="com.JavaClass.pojo.Student"/>
<bean id="study" class="com.JavaClass.pojo.Study"/>
<bean id="teacher" class="com.JavaClass.pojo.Teacher"/>
运行结果如下:

 

98df8891b9b58c9db001e9f663602c9e.png

 @Resource 默认是通过 id 来查找 bean,而配置的两个 cat 的 bean 没有一个名称为默认查找的 cat,故而创建失败。

修改 @Resource,加入参数

@Resource(name = "student1")
private Student student;
@Resource
private Study study;
private String name;

再次执行程序:

 

9423d3f7181b526677df1d73c05417b8.png

程序没问题了

 @Resource总结:

@Resource 注解在 Spring 中默认先尝试通过 bean 的名称(byName)进行自动装配。如果容器中不存在与指定名称相匹配的 bean,则会退回到通过 bean 的类型(byType)进行匹配。但是,如果在类型匹配时找到多个相同类型的 bean,并且没有通过 name 属性指定具体的 bean 名称来消除歧义,或者根本找不到任何该类型的 bean,那么自动装配将失败,并会抛出一个异常。

 

 

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

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

相关文章

使用js实现excel的读取展示以及导出

代码 <!DOCTYPE html> <html lang"zh"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>Document</title><link rel"st…

Unity如何保存玩家的数据(Unity的二进制序列化)

文章目录 什么是二进制序列化读写文件构造函数 自定义二进制序列化 什么是二进制序列化 Unity中的二进制序列化是一种将游戏对象或数据结构转换为二进制格式的过程&#xff0c;以便于存储或网络传输。这使数据能够以高效的方式保存&#xff0c;同时在需要时可以被正确地恢复&a…

傅佩荣讲座视频全集百度网盘,傅佩荣讲座视频大全百度云

在当今信息爆炸的时代&#xff0c;获取知识的途径日益多元化&#xff0c;其中&#xff0c;通过网络观看各类教学视频已成为众多学习者的首选。傅佩荣教授的视频课程深受广大学者的喜爱。然而&#xff0c;对于许多初学者来说&#xff0c;如何下载傅佩荣的视频却是一个难题。本文…

Flutter 面试八股之深入理解 Dart 异步实现机制

为什么写这一篇内容&#xff1f;因为在此之前关于 《面试题里有意思的异步问题》 的文章收到一些「问题」&#xff0c;但是解释这些「问题」并不是“三言两语”就可以说清&#xff0c;所以干脆做一篇完整解析&#xff0c;相信本篇可以帮助你从头到尾理清 Flutter 里 Dart 的完整…

创新、引领、发展——SAMPE中国2024年会在京盛大开幕

绿树阴浓夏日长&#xff0c;在这个色彩缤纷的季节&#xff0c;SAMPE中国2024年会暨第十九届国际先进复合材料制品原材料、工装及工程应用展览会在中国国际展览中心&#xff08;北京朝阳馆&#xff09;隆重开幕。新老朋友共聚一堂&#xff0c;把酒话桑麻。 为期4天的国际学术会…

公共筛选组件(二次封装antd)支持代码提示

如果项目是基于antd组件库为基础搭建&#xff0c;可使用此公共筛选组件 使用到的库 npm i antd npm i lodash-es npm i types/lodash-es -D/components/CommonSearch index.tsx import React from react; import { Button, Card, Form } from antd; import styles from ./…

LED显示屏的换帧频率与刷新频率:技术细节与市场发展

在当今数字化时代&#xff0c;LED显示屏已成为信息传递和广告宣传的重要工具。然而&#xff0c;对于普通消费者来说&#xff0c;LED显示屏背后的技术细节可能仍然是一个谜。今天&#xff0c;我们将深入探讨LED显示屏中的两个关键概念&#xff1a;换帧频率和刷新频率&#xff0c…

ARM功耗管理软件之WFIWFE

安全之安全(security)博客目录导读 思考&#xff1a;功耗管理软件栈及示例&#xff1f;WFI&WFE&#xff1f;时钟&电源树&#xff1f;DVFS&AVS&#xff1f; ARM功耗管理精讲与实战汇总参见&#xff1a;Arm功耗管理精讲与实战

PS系统教程26

PS与BR的关系 如何把图片以图层的方式导入画板里面 选中三张图片/多张选择工具-PS-将文件载入PS图层意味着这三张图片以图层的方式嵌入PS中 拼接长图 裁剪图片 保存裁剪后的图片拼接图片选中要拼接的图片选择工具-PS-Photomerge(拼合图像&#xff09; 图像处理器 大白话&…

APM教程-SkyWalking安装和配置

SkyWalking简介 APM (Application Performance Management) 即应用性能管理&#xff0c;属于IT运维管理&#xff08;ITOM)范畴。主要是针对企业 关键业务的IT应用性能和用户体验的监测、优化&#xff0c;提高企业IT应用的可靠性和质量&#xff0c;保证用户得到良好的服务&#…

IDEA中 pom.xml 设置自动提示

IDEA中 pom.xml 自动提示 IDEA中 pom.xml 自动提示设置如下&#xff1a; file–>Settings–>Build,Execution…–>Build Tools–>Maven–>Repositories 会看到类似表格的画面&#xff0c;内容是你的maven地址&#xff0c;选中后&#xff0c;右边有个Update的按…

轻量级在线服装3D定制引擎Myway简介

我写的面向web元宇宙轻量级系列引擎中的另外一个&#xff0c;在线3D定制引擎Myway 3D。 用于在线商品定制&#xff0c;比如个性化服装的定制、日常用品&#xff08;如杯子&#xff09;、家装&#xff08;被套&#xff09;等物品的在线定制。 特性列表&#xff1a; 可更换衣服…

会话会话会话

目录 1.会话 1.1 为什么需要会话控制 1.2 域对象的范围 1.2.1 应用域的范围 1.2.2 请求域的范围 1.2.3 会话域的范围 1.3 Cookie技术 1.3.1 Cookie的概念 1.3.2 Cookie的作用 1.3.3 Cookie的应用场景 1.3.4 Cookie的入门案例 ① 目标 ② Cookie相关的API ③ Serv…

Python自动化(8)——pyqt5界面

Python自动化(8)——pyqt5界面 注意&#xff1a;pyqt5的界面使用时必须有app QApplication(sys.argv)这行代码&#xff0c;否则会出现错误并且无法显示窗口&#xff1a;QWidget: Must construct a QApplication before a QWidget 一些基础的控件 QMainWindow QMainWindow是…

ESP32 esp-idf esp-adf环境安装及.a库创建与编译

简介 ESP32 功能丰富的 Wi-Fi & 蓝牙 MCU, 适用于多样的物联网应用。使用freertos操作系统。 ESP-IDF 官方物联网开发框架。 ESP-ADF 官方音频开发框架。 文档参照 https://espressif-docs.readthedocs-hosted.com/projects/esp-adf/zh-cn/latest/get-started/index.…

(1995-2022年) 全国各省份-技术交易活跃度

技术交易活跃度是一个关键指标&#xff0c;用于衡量技术市场的交易频繁程度和活跃性。它不仅显示了市场参与者对技术交易的参与热情&#xff0c;而且交易的频率也体现了市场的活力。这一指标对于不同的利益相关者具有不同的意义&#xff1a; 对投资者而言&#xff0c;技术交易…

尚硅谷k8s

p1-6 阿里云服务器开通流程 阿里云服务器购买等各种操作,省略 p7 私有网络vpc实战 VPC&#xff08;Virtual Private Cloud&#xff09;网络&#xff0c;是一种基于云计算的网络服务&#xff0c;旨在为用户提供在公有云上自定义的、逻辑隔离的网络空间。 设置vpc可以使网络之…

让生产管理变简单

随着业务的发展&#xff0c;工厂每天要处理很多订单&#xff0c;还要统筹安排各部门工作以及协调上下游加工企业&#xff0c;生产管理问题也随之而来。 1.销售订单评审困难、无法及时抓取到历史数据做参考。由于数据的不及时性、不准确性无法为正常的生产和采购提供数据支撑。同…

Linux关闭swap分区操作[适用于CDH报警等]

1.查看swap分区挂载路径(没卵用) swapon -s 2.设置配置文件的swap配置 echo “vm.swappiness 0” > /etc/sysctl.conf 3.设置内存中的swap状态。有时候配置文件为0&#xff0c;但集群或服务仍然使用了swap分区&#xff0c;可能原因就是内存没有同步配置 echo “0” > …

X-AnyLabeling使用教程

1.AI 模型自动分割标注使用教程 2.AI 模型自动目标检测标注使用教程