【Spring】— Spring中Bean的装配方式

news2025/2/27 8:30:01

Spring中Bean的装配方式

    • Bean的装配方式
      • 1.基于XML的装配
      • 2.基于Annotation的装配
      • 3.自动装配

Bean的装配方式

    Bean的装配可以理解为依赖关系注入,Bean的装配方式即Bean依赖注入的方式。Spring容器支持多种形式的Bean装配方式,如基于XML的装配基于Annotation(注解)的装配自动装配等。

1.基于XML的装配

    Spring提供了两种基于XML的装配方式:设值注入(Setter Injection)和构造注入(Constructor Injection)。下面讲解如何在XML配置文件中使用这两种注入方式来实现基于XML的装配。在Spring实例化Bean的过程中,Spring首先会调用Bean的默认构造方法来实例化Bean对象,然后通过反射的方式调用setter()方法来注入属性值。因此,设值注入要求一个Bean必须满足以下两点要求:

  • Bean类必须提供一个默认的无参构造方法。
  • Bean类必须为需要注入的属性提供对应的setter()方法。

    使用设值注入时,在Spring配置文件中需要使用bean元素的子元素property来为每个属性注入值;

    使用构造注入时,在配置文件中需要使用bean元素的子元素constructor-arg来定义构造方法的参数,可以使用其value属性(或子元素)来设置该参数的值。

    【示例2-2】下面通过一个案例来演示基于XML方式的Bean的装配。

    (1)在项目chapter02的src目录下创建一个com.ssm.assemble包,在该包中创建User类,并在类中定义userName、password和list集合3个属性及对应的setter()方法。

User.java

package com.ssm.assemble;

import java.util.List;

/**
 * 功能描述
 *
 * @author: 衍生星球
 * @date: 2023年04月14日 8:24
 */

public class User {
    private String userName;
    private String password;
    private List<String> list;

    /**
     * 1.使用构造注入
     * 1.1提供带所有参数的构造方法
     */
    public User(String userName,String password,List<String> list) {
        super();
        this.userName = userName;
        this.password = password1;
        this.list = list;
    }
    @Override
    public String toString () {
        return "User[userName = " +userName+ ", password1 = "+password1+", list = "+list+"]";
    }
    /**
     * 2.使用设值注入
     * 2.1提供默认空参构造方法
     * 2.2为所有属性提供setter()方法
     */
    public User() {
        super();
    }
    public void setUserName(String userName) {
        this.userName = userName;
    }
    public void setPassword(String password) {
        this.password = password;
    }
    public void setList(List<String> list) {
        this.list = list;
    }
}

    由于要使用构造注入,因此需要编写有参和无参的构造方法。

    (2)在Spring的配置文件application.xml中,增加通过构造注入和设值注入的方法装配User实例的两个Bean。

 	<bean id="user1" class="com.ssm.assemble.User">
        <constructor-arg index="0" value="zhangsan" />
        <constructor-arg index="1" value="111111" />
        <constructor-arg index="2">
            <list>
                <value>"constructorValue1"</value>
                <value>"constructorValue2"</value>
            </list>
        </constructor-arg>
    </bean>
    <bean  id="user2" class="com.ssm.assemble.User">
        <property name="userName" value="lisi"></property>
        <property name="password" value="222222"></property>
        <property name="list">
            <list>
                <value>listValue1</value>
                <value>listValue2</value>
            </list>
        </property>
    </bean>

     在上述代码中,constructor-arg元素用于定义构造方法的参数,其属性index表示其索引(从0开始),value属性用于设置注入的值,其子元素list为User类中对应的list集合属性注入值

     然后又使用设值注入方法装配User类的实例,其中property元素用于调用Bean实例中的setter()方法完成属性赋值,从而完成依赖注入,而其子元素list同样为User类中对应的list集合属性注入值。

     (3)在com.ssm.assemble包中创建测试类XmlAssembleTest,在类中分别获取并输出配置文件中的user1和user2实例。

XmlAssembleTest.java

package com.ssm.assemble;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * @author: 衍生星球
 * @date: 2023年04月14日 9:08
 */

public class XmlAssembleTest {
    public static void main(String[] args) {
        //1.初始化Spring容器,加载配置文件
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
        //2.输出获得的实例
        System.out.println(applicationContext.getBean("user1"));
        System.out.println(applicationContext.getBean("user2"));
    }
}

     执行程序后,控制台输出结果如下。可以看出,已经成功地使用基于XML装配的构造注入和设值注入两种方式装配了User实例。

在这里插入图片描述

2.基于Annotation的装配

     在Spring中,尽管使用XML配置文件可以实现Bean的装配工作,但如果应用中有很多Bean,就会导致XML配置文件过于臃肿,给以后的维护和升级工作带来一定的困难。为此,Spring提供了对Annotation(注解)技术的全面支持。Spring中定义了一系列的注解,常用的注解如表所示。

在这里插入图片描述

     注意:虽然@Repository、@Service和@Controller的功能与@Component注解的功能相同,但为了使标注类本身用途更加清晰,建议在实际开发中使用@Repository、@Service和@Controller分别对实现类进行标注。

     【示例2-3】接下来,通过一个案例来演示如何通过这些注解来装配Bean。
     (1)在chapter02项目的src目录下创建一个com.ssm.annotation包,在该包中创建接口UserDao,并在接口中定义一个save()方法。

UserDao.java

package com.ssm.annotation;

public interface UserDao {
    public void save();
}

     (2)在com.ssm.annotation包中创建UserDao接口的实现类UserDaoImpl,该类需要实现接口中的save()方法。

UserDaoImpl.java

package com.ssm.annotation;

import org.springframework.stereotype.Repository;

/**
 * 功能描述
 *
 * @author: 衍生星球
 * @date: 2023年04月14日 9:43
 */
 //使用 @Repository 注解将 UserDaoImpl 类标识为 Spring 中的 Bean
@Repository("userDao")
public class UserDaoImpl implements UserDao {
    public void save() {
        System.out.println("userDao,save");
    }
}

     首先使用@Repository注解将UserDaoImpl类标识为Spring中的Bean,其写法相当于配置文件中 <bean id="userDao" class="com.ssm.annotation.UserDaoImpl />的编写。然后在save()方法中打印一句话,用于验证是否成功调用了该方法。

     (3)在com.ssm.annotation包中创建接口UserService,在接口中同样定义一个save()方法。

UserService.java

package com.ssm.annotation;

public interface UserService {
    public void save();
    
}

     (4)在com.ssm.annotation包中创建UserService接口的实现类UserServiceImpl,该类需要实现接口中的save()方法。

UserServiceImpl.java

package com.ssm.annotation;

import org.springframework.stereotype.Service;

import javax.annotation.Resource;

/**
 * 功能描述
 *
 * @author: 衍生星球
 * @date: 2023年04月14日 14:26
 */
//使用 @ 注解将 UserServiceImpl 类标识为 Spring 中的 Bean
@Service("userService")
public class UserServiceImpl implements UserService {
    //使用 @Resource 注解注入
    @Resource(name="userDao")
    private UserDao userDao;
    public void save() {
        this.userDao.save();
        System.out.println("执行userService.save()");
    }
}

     首先使用@Service注解将UserServiceImpl类标识为Spring中的Bean,这相当于配置文件中<bean id= "userService"class="com.ssm.annotation.UserServiceImpl"/>的编写;

     然后使用@Resource注解标注在属性userDao上,这相当于配置文件中<property name="userDao" ref="userDao"/>的写法;最后在该类的save()方法中调用userData中的save()方法,并输出一句话。

    (5)在com.ssm.annotation包中创建控制器类UserController。

UserController.java

package com.ssm.annotation;

import org.springframework.stereotype.Controller;

import javax.annotation.Resource;

/**
 * 功能描述
 *
 * @author: 衍生星球
 * @date: 2023年04月14日 16:21
 */
//使用 @Controller 注解将 UserController 类标识为 Spring 中的 Bean
@Controller("UserController")
public class UserController {
    //使用 @Resource 注解注入
    @Resource(name = "UserService")
    private UserService userService;
    public void save() {
        this.userService.save();
        System.out.println("运行userService.save()");
    }
}

     首先使用@Controller注解标注了UserController类,这相当于在配置文件中编写<bean id="userController" class=" com.ssm.annotation.UserController"/>

     然后使用@Resource注解标注在userService属性上,这相当于在配置文件中编写<property name="userService" ref=" userService"/>;最后在其save()方法中调用了userService中的save()方法,并输出一句话。

     (6)创建配置文件beans1.xml,在配置文件中编写基于Annotation装配的代码。

beans1.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"
       xmlns:context="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">
       
    <!-- 使用context命名空间在配置文件中 开启相应的注解处理器 -->
    <context:annotation-config/>
    <!-- 分别定义3个 bean 实例 -->
    <bean id="UserDao" class="com.ssm.annotation.UserDaoImpl" />
    <bean id="UserService" class="com.ssm.annotation.UserServiceImpl" />
    <bean id="UserController" class="com.ssm.annotation.UserController" />
</beans>

     在<beans>元素中增加了包含context的约束信息;然后通过配置<context: annotation-config/>来开启注解处理器;最后分别定义了3个Bean对应的3个实例。与XML配置方式有所不同的是,这里不再需要配置子元素<property>。上述Spring配置文件中的注解方式虽然较大程度地简化了XML文件中Bean的配置,但仍需在Spring配置文件中一一配置相应的Bean,为此Spring注解提供了另一种高效的注解配置方式(对包路径下的所有Bean文件进行扫描),其配置方式如下:

<context:component-scan base-package="Bean所在的包路径" />

代码进行如下替换:

<!-- 使用context命名空间通知 Spring 扫描指定包下所有的 Bean类,进行注解解析 -->
<context:component-scan base-package="com.ssm.annotation" />

    (7)在com.ssm.annotation包中创建测试类AnnotationAssembleTest,在类中编写测试方法并定义配置文件的路径,然后通过Spring容器加载配置文件并获取UserController实例,最后调用实例中的save()方法。

AnnotationAssembleTest.java

package com.ssm.annotation;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * 功能描述
 *
 * @author: 衍生星球
 * @date: 2023年04月14日 16:47
 */

public class AnnotationAssembleTest {
    private static ApplicationContext applicationContext;
    public static void main(String[] args) {
        //1.定义配置文件路径
        String xmlPath = "beans1.xml";
        applicationContext = new ClassPathXmlApplicationContext("xmlPath");
        //2.获取 UserController 实例
        UserController userController = (UserController) applicationContext.getBean("UserController");
        //3.调用 UserController中的save()方法
        userController.save();
    }
}

    执行程序后,控制台的输出结果如图所示。从中可以看到,Spring容器已成功获取了UserController的实例,并通过调用实例中的方法执行了各层中的输出语句,这说明已成功实现了基于Annotation来装配Bean实例。

在这里插入图片描述
    注意:上述案例中使用@Autowired注解替换@Resource注解也可以达到同样的效果。

3.自动装配

    虽然使用注解的方式装配Bean在一定程度上减少了配置文件中的代码量,但是也有企业项目中是没有使用注解方式开发的,那么有没有什么办法既可以减少代码量,又能够实现Bean的装配呢?

    Spring的<bean>元素中包含一个autowire属性,我们可以通过设置autowire的属性值来自动装配Bean。所谓自动装配,就是将一个Bean自动注入其他Bean的Property中。autowire属性有5个值,其值及说明如表所示。

在这里插入图片描述

    【示例2-4】下面通过修改2.3.2节中的案例来演示如何使用自动装配。
    (1)修改UserServiceImpl.java和UserController.java,分别在这两个文件中增加类属性的setter()方法。
    (2)修改beans1.xml,将其修改成自动装配形式。

	<!-- 使用bean元素的autowire属性完成自动装配   -->
    <bean id="UserDao" class="com.ssm.annotation.UserDaoImpl" />
    <bean id="UserService" class="com.ssm.annotation.UserServiceImpl" autowire="byName" />
    <bean id="UserController" class="com.ssm.annotation.UserController" autowire="byName" />

    在上述配置文件中,用于配置userService和userController的<bean>元素中除了id和class属性外,还增加了autowire属性,并将其属性值设置为byName。在默认情况下,配置文件中需要通过ref来装配Bean,但设置了autowire="byName"后,Spring会自动寻找userServiceBean中的属性,并将其属性名称与配置文件中定义的Bean做匹配。由于UserServiceImpl中定义了userDao属性及其setter()方法,这与配置文件中id为userDao的Bean相匹配,因此Spring会自动地将id为userDao的Bean装配到id为userService的Bean中。执行程序后,控制台的输出结果如图所示。

在这里插入图片描述

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

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

相关文章

电力系统中针对状态估计的虚假数据注入攻击建模与对策(Matlab代码实现)

&#x1f352;&#x1f352;&#x1f352;欢迎关注&#x1f308;&#x1f308;&#x1f308; &#x1f4dd;个人主页&#xff1a;我爱Matlab &#x1f44d;点赞➕评论➕收藏 养成习惯&#xff08;一键三连&#xff09;&#x1f33b;&#x1f33b;&#x1f33b; &#x1f34c;希…

免费部署属于自己的chatGPT网站,欢迎大家试玩

最近我发现了一个非常nice的部署网站的工具&#xff0c; railway&#xff0c;这个网站是国外的&#xff0c;所以部署出来的项目域名是国外的&#xff0c;并不需要担心封号&#xff0c;也不需要进行域名注册&#xff0c;部署成功之后会自动生成域名&#xff0c;在国内就能够正常…

[NSSRound#11] 密码学个人赛

这个比赛没有参加,跟别人要了些数据跑一下,其实交互这东西基本上一样,跑通就行. ez_enc 这题有点骗人,给了一堆AB串,一开始以为是培根密码,结果出来很乱.再看长度:192 应该就是01替换 a ABAABBBAABABAABBABABAABBABAAAABBABABABAAABAAABBAABBBBABBABBABBABABABAABBAABBABAA…

“心机boy”马斯克:明面上呼吁暂停先进AI研发,背地里悄悄买1万块GPU推进大模型项目

来源: AI前线 微信号&#xff1a;ai-front 整理 | 冬梅、核子可乐 为了研发自家 AIGC&#xff0c; 马斯克狂买 GPU 并四处挖人 当地时间 4 月 11 日&#xff0c;据多家外媒报道&#xff0c;尽管高调建议在整个行业范围内停止 AI 训练&#xff0c;但伊隆马斯克本人倒是在 T…

VMware:安装centos7

环境&#xff1a; 准备好VMware软件 准备好centos镜像 如有需要 寻找镜像&&真机安装&&真机安装时候找不到硬盘 可以查看 &#xff1a; linux&#xff1a;真机安装centos linux&#xff08;突发事件&#xff1a;解决卡在安装界面&#xff09;{寻找镜像--u…

springboot+vue简历系统(源码+文档)

风定落花生&#xff0c;歌声逐流水&#xff0c;大家好我是风歌&#xff0c;混迹在java圈的辛苦码农。今天要和大家聊的是一款基于springboot的简历系统简历系统。项目源码请联系风歌&#xff0c;文末附上联系信息 。 目前有各类成品java毕设&#xff0c;需要请看文末联系方式 …

Excel中的表格批量生成word表格

场景&#xff1a;测试用例excel转word 我们在项目中&#xff0c;默认情况下是用我们的excel用例模版输出测试用例。但是有的项目中&#xff0c;会要求在word版本的测试计划或者测试报告中&#xff0c;写明测试用例。而我们的测试用例&#xff0c;有的项目有上千条&#xff0c;…

基于遥感的自然生态环境检测——实验一:SPOT全色影像正射纠正

实验流程 实验总流程如下图所示&#xff0c;主要包括四大步&#xff1a; &#xff08;1&#xff09;SPOT全色影像正射纠正&#xff1b; &#xff08;2&#xff09;多光谱与全色影像的配准和融合&#xff1b; &#xff08;3&#xff09;大气校正和生态因子提取&#xff1b; &am…

MathType+MicrosoftWord

MathTypeMicrosoftWordMathType的安装Microsoft WordMathType的安装 链接&#xff1a;https://pan.baidu.com/s/1bEd41GF-yRCRw2tb1XH8og?pwd1234 提取码&#xff1a;1234 语言选择英文&#xff01;&#xff01;&#xff01; 安装好之后&#xff0c;按win键&#xff0c;可以…

Springboot项目实战:一个依赖解决多平台OSS文件上传问题,以后就用这个 oss-spring-boot-starter

本文解决痛点。是否再不同项目需要不同的OSS二头疼。 A项目用七牛云&#xff0c;B项目使用阿里云。不想用七牛云了&#xff0c;还是改用华为云吧。同个项目使用不同的 bucketName 遇到这种种情况&#xff0c;本文提供一个依赖搞定多云OSS 适配问题 什么是OSS? 数据以对象&…

【UE 控件蓝图】菜单及功能实现

素材资源连接&#xff1a;百度网盘 请输入提取码 密码&#xff1a;fvcw 效果 步骤 1. 创建蓝图&#xff0c;父类为“HUD” 命名为“MainMenuHUD”并打开 在事件图表中添加如下节点&#xff1a; 2. 创建控件蓝图&#xff0c;命名为“MainMenuWidget” 此时在“MainMenuHUD”的…

全方位解析 pinia

前言 Vue3已经推出很长时间了&#xff0c;它周边的生态也是越来越完善了。之前我们使用Vue2的时候&#xff0c;Vuex可以说是必备的&#xff0c;它作为一个状态管理工具&#xff0c;给我们带来了极大的方便。Vue3推出后&#xff0c;虽然相对于Vue2很多东西都变了&#xff0c;但…

私有句柄表

私有句柄表 实验环境 win7 x86 什么是私有句柄表&#xff1f; 私有句柄表是操作系统内部的一种数据结构&#xff0c;用于存储一个进程所拥有的句柄&#xff08;或称为句柄对象&#xff09;的信息。在操作系统中&#xff0c;句柄是一个标识符&#xff0c;用于唯一标识一个对…

【iOS】NSError**和__autoreleasing场景

前言 在看JSONModel源码的时候&#xff0c;JSONModel的自定义Error的方法一直在报错 - (BOOL)validate:(NSError *__autoreleasing *)error {}这个方法在定义error的时候添加上了__autoreleasing修饰符&#xff0c;涉及到了__autoleasing的显式隐式调用就去了解了一下。 发现…

【C++ 三】一维数组、二维数组

数组概述、一维数组、二维数组 文章目录数组概述、一维数组、二维数组前言1 数组1.1 概述2 一维数组2.1 一维数组定义方式2.2 一维数组数组名2.3 冒泡排序3 二维数组3.1 二维数组定义方式3.2 二维数组数组名总结前言 本文包含数组概述、一维数组、二维数组。 1 数组 1.1 概述…

python web 医院加密处方系统

医院加密处方系统 环境要求&#xff1a; 1、python3.8 2、vue 3、django 4、mysql 5、ruoyi快速开发框架 登录界面 可以登录和注册&#xff0c;注册分三个角色&#xff0c;主治医师和药品医师还有配制医师&#xff0c;有验证码和用户权限功能&#xff0c;用户管理、部…

AIGC下一站:期待、警惕充斥着AI剪辑师的世界

上月底&#xff0c;名为“chaindrop”的 Reddit 用户&#xff0c;在 r/StableDiffusion subreddit 上分享了一个由人工智能生成的视频&#xff0c;在业内引起了不小的争议。 视频中&#xff0c;一个由 AI 生成的丑陋畸形的 “威尔史密斯”&#xff0c;以一种可怕的热情将一把意…

vba:消息框基础,massagebox

常量常量值说明vbOKOnly0只显示“确定”按钮&#xff08;缺省值&#xff09;VbOKCancel1显示“确定”和“取消”按钮VbAbortRetryIgnore2显示“终止”、“重试”和“忽略” 按钮VbYesNoCancel3显示“是”、“否”和“取消”按钮VbYesNo4显示“是”和“否”按钮VbRetryCancel5显…

pkg-config

前言 在介绍 pkg-config 之前&#xff0c;先讲一个我的经历。 有一次我想用 libgtk 库在 ubuntu 上实现一个简单的图形界面&#xff0c;就像下面代码 #include <gtk/gtk.h>int main(int argc, char *argv[]) {GtkWidget *window;gtk_init(&argc, &argv);window…

UG NX二次开发(C#)-建模-获取曲面的法矢

文章目录 1、前言2、曲面的法矢示例3、获取曲面的法矢3.1 采用 uFModl.AskFaceProps实现3.2采用 uFSo实现4、结论1、前言 在UG NX二次开发过程中,我们想获取曲面的法矢,是通过ufun函数来获取的。我们以一个平面和一个曲面来说明其开发过程。 2、曲面的法矢示例 创建一张曲…