Spring中的Bean

Spring中的Bean

目录:

一、Bean的配置

二、Bean的实例化

三、Bean的作用域

四、Bean的装配方式

一、Bean的配置
1.IoC 容器

​ Spring容器会负责控制程序之间的关系,而不是由程序代码直接控制,这样控制权由应用代码转移到了外部容器,控制权发生了反转,也就是Spring的IoC(Inversion of Control, IoC)思想。Spring为我们提供了两种IoC容器,分别为BeanFactory和ApplicationContext。如果把Spring看做一个大型的工厂,而Spring容器中的Bean就是工厂的产品。要想使用工厂生产和管理的Bean,就需要在配置文件中告诉它容器中有那些Bean,接下来我们将介绍如何将这些Bean放入到容器中。

Spring 容器的核心:用于消减代码耦合问题。

2.Spring 配置文件

Spring 容器支持两种格式的 配置文件Properties 文件XML 文件

在实际开发中,最常使用的是XML文件格式的配置方式,这种配置方式是通过XML文件来注册并管理Bean之间的依赖关系。

XML配置文件的根元素是中包含了多个子元素,每一个子元素定义了一个Bean,并描述了该Bean如何被装配到Spring容器中。定义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"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"><!-- 使用id属性定义bean1,其对应的实现类为cn.itcast.bean1 --><bean id="bean1" class=“edu.cqie.ssm.bean1"/><!-- 使用name属性定义bean2,其对应的实现类为cn.itcast.bean2 --><bean name="bean2" class=“edu.cqie.ssm.bean2"/>
</beans>

注意:通常一个普通的Bean只需要定义id(或name)和class 两个属性即可,如果在Bean中未指定id和name,则Spring会将class值当作id使用。

元素,常用属性包含以下这些属性,具体如下表所示:

在这里插入图片描述

二、Bean的实例化
1.Spring 容器实例化 Bean

在面向对象的程序中,要想使用某个对象,就需要先实例化这个对象。在Spring中,常见的实例化Bean有三种方式,分别是构造器实例化、静态工厂方式实例化和实例工厂方式实例化,接下来对这几种方式进行详细介绍:

(1) 构造器方式

构造器实例化是指Spring容器通过Bean对应的类中默认的构造函数来实例化Bean,这种方式也是最常用的。

案例:

package com.example;public class User {private String name;private int age;// 默认无参构造函数public User() {}// 带参数的构造函数public User(String name, int age) {this.name = name;this.age = age;}// Getter和Setter方法public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}
}
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans.xsd"><!-- 使用默认构造函数创建User Bean --><bean id="user" class="com.example.User"><!-- 使用属性注入设置name和age --><property name="name" value="张三"/><property name="age" value="30"/></bean></beans>

在这个XML配置中:

标签定义了一个id为user的Bean,class属性指定了Bean的全限定类名(这里假设为com.example.User)。
由于User类有一个默认的无参构造函数,Spring容器可以使用这个构造函数来实例化User对象。
标签用于注入Bean的属性。这里我们设置了name和age属性的值。
当Spring容器加载这个配置文件时,它会使用User类的默认无参构造函数来创建一个User对象的实例,然后通过setter方法注入name和age属性的值。这种方式简单且常用,因为它允许在不修改类代码的情况下灵活地配置Bean的属性。

(2) 静态工厂方式

使用静态工厂是实例化Bean的另一种方式。该方式要求自己创建一个静态工厂的方法来创建Bean的实例。

案例:

package com.example;public class Car {private String brand;private Car(String brand) {this.brand = brand;}public String getBrand() {return brand;}// 静态工厂方法public static Car getCar(String brand) {return new Car(brand);}
}
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans.xsd"><!-- 使用静态工厂方法创建Car Bean --><bean id="myCar" class="com.example.Car"><constructor-arg value="宝马"/></bean><!-- 或者使用factory-method方式 --><bean id="myCar" class="com.example.Car" factory-method="getCar"><constructor-arg value="宝马"/></bean></beans>

在这个XML配置中:

第一个标签尝试使用Car类的构造函数来创建Bean,但由于Car类的构造函数是私有的,这种方式会失败。
第二个标签使用factory-method属性指定了静态工厂方法getCar,constructor-arg标签提供了静态工厂方法需要的参数。这种方式可以成功创建Car的实例。
静态工厂方法实例化提供了一种灵活的方式来创建Bean,特别是当你需要根据参数动态决定返回哪个类的实例时。这种方式也有助于保持代码的模块化,因为实例化的逻辑被封装在工厂方法中。

(3) 实例工厂方式

实例化工厂方式的工厂类中,不再使用静态方法创建Bean实例,而是采用直接创建Bean实例的方式。同时,在配置文件中,需要实例化的Bean也不是通过class属性直接指向其实例化的类,而是通过factory-bean属性配置一个实例工厂,然后使用factory-method属性确定使用工厂中的哪个方法。

案例:

package com.example;public class Car {private String brand;private Car(String brand) {this.brand = brand;}public String getBrand() {return brand;}
}// 工厂类
public class CarFactory {private String defaultBrand;public CarFactory(String defaultBrand) {this.defaultBrand = defaultBrand;}// 实例工厂方法public Car createCar() {return new Car(defaultBrand);}
}
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans.xsd"><!-- 定义CarFactory Bean --><bean id="carFactory" class="com.example.CarFactory"><constructor-arg value="宝马"/></bean><!-- 使用实例工厂方法创建Car Bean --><bean id="myCar" factory-bean="carFactory" factory-method="createCar"/>
</beans>

在这个XML配置中:

我们首先定义了一个CarFactory的Bean,id为carFactory,并使用构造函数注入了一个默认的品牌名称。
然后,我们定义了一个Car的Bean,id为myCar。我们使用factory-bean属性指定了工厂Bean的id,使用factory-method属性指定了实例工厂方法的名称。这样,Spring容器会调用carFactory实例的createCar方法来创建myCar的实例。
实例工厂方法实例化提供了一种灵活的方式来创建Bean,特别是当你需要在创建Bean之前对工厂Bean进行复杂的初始化,或者需要同一个工厂实例来创建多个Bean时。这种方式也有助于保持代码的模块化,因为实例化的逻辑被封装在工厂方法中。

(4) 实例工厂变种方式

与实例化工厂方式不同的是,自定义工厂类需要实现FactoryBean接口,通过覆写接口的getObject()、getObjectType()和 isSingleton()方法来创建Bean。同时,在配置文件中需将该工厂Bean注册到容器中。

案例:

package com.example;public interface Car {void drive();
}public class SportsCar implements Car {@Overridepublic void drive() {System.out.println("Driving a sports car");}
}public class SedanCar implements Car {@Overridepublic void drive() {System.out.println("Driving a sedan car");}
}// 工厂类
public class CarFactory {// 实例工厂方法,根据传入的类型参数创建不同类型的Car实例public Car createCar(String type) {if ("sports".equalsIgnoreCase(type)) {return new SportsCar();} else if ("sedan".equalsIgnoreCase(type)) {return new SedanCar();}throw new IllegalArgumentException("Unknown car type: " + type);}
}
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans.xsd"><!-- 定义CarFactory Bean --><bean id="carFactory" class="com.example.CarFactory"/><!-- 使用实例工厂方法创建SportsCar Bean --><bean id="sportsCar" factory-bean="carFactory" factory-method="createCar"><constructor-arg value="sports"/></bean><!-- 使用实例工厂方法创建SedanCar Bean --><bean id="sedanCar" factory-bean="carFactory" factory-method="createCar"><constructor-arg value="sedan"/></bean></beans>

在这个XML配置中:

我们首先定义了一个CarFactory的Bean,id为carFactory。
然后,我们定义了两个Car类型的Bean,id分别为sportsCar和sedanCar。我们使用factory-bean属性指定了工厂Bean的id,使用factory-method属性指定了实例工厂方法的名称,并使用constructor-arg标签提供了实例工厂方法需要的参数。这样,Spring容器会调用carFactory实例的createCar方法,并根据参数的不同来创建SportsCar或SedanCar的实例。
实例工厂变种方式提供了一种灵活的方式来创建Bean,特别是当你需要根据不同的条件或参数来创建不同类型的Bean实例时。这种方式也有助于保持代码的模块化,因为实例化的逻辑被封装在工厂方法中。

(5) 注解方式

创建一个配置类,在该类上添加@Configuration注解,如果在配置类中编写一个方法,并给该方法添加上@Bean注解时,该方法将会创建一个bean的实例,这个实例将会被注册到Spring容器中。

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration // 告诉Spring这是一个配置类
public class AppConfig {// 使用@Bean注解来声明一个Bean,并返回这个Bean的实例@Beanpublic MyBean myBean() {return new MyBean();}
}// MyBean类的定义
class MyBean {// 类的成员和方法
三、Bean的作用域
1.作用域分类

Spring容器在初始化一个Bean实例时,可以同时为其指定特定的作用域。Spring为Bean实例定义了五种Bean的作用域,这五种作用域说明如下所示:

(1)singleton

​ 单例模式,使用singleton定义的bean在Spring容器中将只有一个实例,也就是说,无论有多少个Bean引用它,始终将指向同一个对象。这也是Spring容器默认的作用域。( singleton作用域是Spring容器默认的作用域,当一个Bean的作用域为singleton时,Spring容器中只会存在一个共享的Bean实例,并且所有对Bean的请求,只要id与该Bean定义相匹配的,就只会返回Bean的同一个实例。)

在Spring配置文件中,可以使用bean元素的scope属性,将Bean的作用域定义成singleton。

<bean id="hello"   class="edu.cqie.ssm.Hello"   scope="singleton"/>
(2)prototype

​ 原型模式(也可以是多例模式),每次通过Spring容器获取的prototype定义的Bean时,容器都将创建一个新的Bean实例。( 在使用prototype作用域时,Spring容器会为每个对该Bean的请求都创建一个新的实例。要将Bean定义为prototype,只需在xml文件中将元素的scope属性的值设置为prototype即可。)

<bean id="hello"  class="edu.cqie.ssm.Hello" scope="prototype "/>
(3)request

​ 在一次HTTP请求中,容器会返回该Bean的同一个实例。而对不同的HTTP请求则会产生一个新的Bean,而且该Bean仅在当前HTTP Request内有效。

(4)session

​ 在一次HTTP Session中,容器会返回该Bean的同一个实例。而对不同的HTTP请求则会产生一个新的Bean,而且该Bean仅在当前HTTP Session内有效。

2.Bean 的生命周期

在这里插入图片描述

四、Bean的装配方式

Bean的装配可以理解为Bean的依赖关系注入过程,而依赖注入(DI,Dependency Injection)是控制反转的另外一种说法,只是从不同角度描述相同的概念。控制反转是指将对象(Bean)交给Spring容器创建,而依赖注入则是指由IoC容器在运行期间动态地将某种依赖资源注入到对象之中,也可以理解为通过Spring容器将Bean赋值给另一个Bean的属性的过程。

Spring框架支持多种Bean的装配方式,常用的方式有:

1.基于XML的装配方式
(1)设值注入 Setter Injection

设值注入要求一个Bean必须满足以下两点要求:

​ Bean类必须提供一个默认的构造方法。

Bean类必须为需要注入的属性提供对应的set方法。

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

(2)构造注入 Constructor Injection

​ 使用构造注入时,在配置文件里使用标签来定义构造方法的参数,可以使用其value属性(或子元素)来设置该参数的值。

2.基于Annotation的装配方式

​ 在Spring中,尽管使用XML配置文件可以实现Bean的装配工作,但如果应用中有很多Bean时,会导致XML配置文件过于臃肿,给后续的维护和升级工作带来一定的困难。为此,Java从JDK1.5以后,提供了Annotation(注解)功能,Spring也提供了对Annotation技术的全面支持。

@Component:可以使用此注解描述Spring中的Bean,但它是一个泛化的概念,仅仅表示一个组件(Bean),并且可以作用在任何层次。使用时只需将该注解标注在相应类上即可。

@Repository:用于将数据访问层 (DAO 层 ) 的类标识为Spring中的Bean,其功能与 @Component 相同。

@Service:通常作用在业务层(Service层),用于将业务层的类标识为Spring中的Bean,其功能与 @Component 相同。

@ Constroller:通常作用在控制层(Controller层),用于将控制层的类标识为Spring中的Bean,其功能与 @Component 相同。

@Configuration **:**通常作用在配置类,配合指定该类中一个或多个@Bean方法,交由Spring加载和生成bean,相当于xml的标签+子标签。

@ Autowired:用于对Bean的属性变量、属性的Set方法及构造函数进行标注,配合对应的注解处理器完成Bean的自动注入工作。默认按照Bean的类型进行装配。

@Resource:其作用与Autowired一样。其区别在于@Autowired默认按照Bean类型装配,而@Resource默认按照Bean实例名称进行装配。@Resource中有两个重要属性:name和type。Spring将name属性解析为Bean实例名称,type属性解析为Bean实例类型。如果指定name属性,则按实例名称进行装配;如果指定type属性,则按Bean类型进行装配;如果都不指定,则先按Bean实例名称装配,如果不能匹配,再按照Bean类型进行装配;如果都无法匹配,则抛出NoSuchBeanDefinitionException异常。

@Qualifier:与@Autowired注解配合使用,会将默认的按Bean类型装配修改为按Bean的实例名称装配,Bean的实例名称由@Qualifier注解的参数指定。

3.自动装配方式

自动装配就是由Spring框架自动将一个Bean注入到其他Bean的Property中。要使用自动装配,就需要配置元素的autowire属性。

autowire 属性有 5 个值,其值说明如下所示。

byName:根据Property的Name自动装配,如果一个bean的name,和另一个bean中的Property的name相同,则自动装配这个bean到Property中。

byType:根据Property的数据类型(Type)自动装配,如果一个bean的数据类型,兼容另一个bean中Property的数据类型,则自动装配。

constructor:根据构造函数参数的数据类型,进行byType模式的自动装配。

autodetect:如果发现默认的构造函数,用constructor模式,否则用byType模式。

no:默认情况下,不使用自动装配,Bean依赖必须通过ref元素定义。

入到其他Bean的Property中。要使用自动装配,就需要配置元素的autowire属性。

autowire 属性有 5 个值,其值说明如下所示。

byName:根据Property的Name自动装配,如果一个bean的name,和另一个bean中的Property的name相同,则自动装配这个bean到Property中。

byType:根据Property的数据类型(Type)自动装配,如果一个bean的数据类型,兼容另一个bean中Property的数据类型,则自动装配。

constructor:根据构造函数参数的数据类型,进行byType模式的自动装配。

autodetect:如果发现默认的构造函数,用constructor模式,否则用byType模式。

no:默认情况下,不使用自动装配,Bean依赖必须通过ref元素定义。

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

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

相关文章

无效的目标发行版17和无法连接Maven进程问题

起因&#xff1a;我clean了一个模块的Maven想要重新下&#xff0c;他就开始报错。两次了都是这样。如果和我一样一开始都是好好的&#xff0c;直接找Maven的设置&#xff0c;在运行程序改&#xff0c;jre变成了11.它自己变成了我其他的jdk

猎板PCB罗杰斯板材的应用案例

以下是几个猎板 PCB 与罗杰斯板材结合的具体案例&#xff1a; 案例一&#xff1a;5G 通信基站天线 PCB 在 5G 通信基站的天线系统中&#xff0c;对高频信号的传输和处理要求极高。猎板 PCB 采用罗杰斯板材&#xff0c;凭借其稳定的低介电常数&#xff08;如 RO4003C 板材&…

ollama+springboot ai+vue+elementUI整合

1. 下载安装ollama (1) 官网下载地址&#xff1a;https://github.com/ollama/ollama 这里以window版本为主&#xff0c;下载链接为&#xff1a;https://ollama.com/download/OllamaSetup.exe。 安装完毕后&#xff0c;桌面小图标有一个小图标&#xff0c;表示已安装成功&…

零基础利用实战项目学会Pytorch

目录 pytorch简介 1.线性回归 2.数据类型 2.1数据类型检验 2.2Dimension0/Rank0 2.3 Dim1/Rank1 2.4 Dim2/Rank2 3.一些方法 4.Pytorch完成分类任务 4.1模型参数 4.2 前向传播 4.3训练以及验证 4.4 三行搞定&#xff01; 4.5 准确率 5、Pytorch完成回归任务 5.…

大数据实验9:Spark安装和编程实践

实验九&#xff1a;Spark基础编程1 一、实验目的 通过实验掌握基本的Spark编程方法&#xff1b;掌握用Spark解决一些基本的数据处理和统计分析&#xff0c;去重、排序等&#xff1b; 二、实验要求 掌握Spark相关shell命令的使用&#xff1b;完成下面的实验内容&#xff0c;…

vue3 element el-table实现表格动态增加/删除/编辑表格行,带有校验规则

需求描述 在项目中遇到需要实现表格动态的新增、编辑、删除表格行的需求&#xff0c;同时带有校验规则 代码解决 点击新增的时候&#xff0c;给新增row默认属性&#xff0c;给相应的默认值&#xff0c;包括给一个isEditor: true&#xff0c;用来区分是否需要编辑。同时当有编…

Redis下载历史版本

Linux版本&#xff1a; https://download.redis.io/releases/ Windows版本&#xff1a; https://github.com/tporadowski/redis/releases Linux Redis对应gcc版本

初识ElasticSearch

一、了解ES 1.1 什么是 ElasticSearch 1、ElasticSearch 是一款非常强大的开源搜索引擎&#xff0c;可以帮助我们从海量的数据中快速的找到需要的内容。 2、ElasticSearch 结合 Kibana、Logstash、Beats、也就是Elastic Stach&#xff08;ELK&#xff09;。被广泛应用在日志数…

【大数据学习 | HBASE高级】hbase-phoenix 与二次索引应用

1. hbase-phoenix的应用 1.1 概述&#xff1a; 上面我们学会了hbase的操作和原理&#xff0c;以及外部集成的mr的计算方式&#xff0c;但是我们在使用hbase的时候&#xff0c;有的时候我们要直接操作hbase做部分数据的查询和插入&#xff0c;这种原生的方式操作在工作过程中还…

Redis在高性能缓存中的应用

&#x1f493; 博客主页&#xff1a;瑕疵的CSDN主页 &#x1f4dd; Gitee主页&#xff1a;瑕疵的gitee主页 ⏩ 文章专栏&#xff1a;《热点资讯》 Redis在高性能缓存中的应用 Redis在高性能缓存中的应用 Redis在高性能缓存中的应用 引言 Redis 概述 定义与原理 发展历程 Redi…

MySQL初学之旅(3)约束

目录 1.前言 2.正文 2.1约束类型 2.2NULL约束 2.3UNIQUE约束 2.4DEFAULT约束 2.5PRIMARY KEY主键约束 2.6FOREIGN KEY外键约束 2.7CHECK约束 3.小结 1.前言 哈喽大家好啊&#xff0c;今儿来继续给大家分享最近学习的MySQL和约束相关的知识点&#xff0c;希望大家一起…

RHCE的学习(20)

变量5种赋值方式 shell中变量赋值5种方式&#xff0c;其中采用name10的方法称A 直接赋值 nameB read命令 read v1C 使用命令行参数 &#xff08;$1 $2 $3 ..&#xff09; name$1D 使用命令的输入 username$(whoami)E 从文件读取 #cut -d : -f1 /etc/passwd > /user.listfor…

Java项目实战II基于微信小程序的电子商城购物平台(开发文档+数据库+源码)

目录 一、前言 二、技术介绍 三、系统实现 四、文档参考 五、核心代码 六、源码获取 全栈码农以及毕业设计实战开发&#xff0c;CSDN平台Java领域新星创作者&#xff0c;专注于大学生项目实战开发、讲解和毕业答疑辅导。获取源码联系方式请查看文末 一、前言 随着互联网…

Godot的开发框架应当是什么样子的?

目录 前言 全局协程还是实例协程&#xff1f; 存档&#xff01; 全局管理类&#xff1f; UI框架&#xff1f; Godot中的异步&#xff08;多线程&#xff09;加载 Godot中的ScriptableObject 游戏流程思考 结语 前言 这是一篇杂谈&#xff0c;主要内容是对我…

【C++】深入理解 C++ 优先级队列、容器适配器与 deque:实现与应用解析

个人主页: 起名字真南的CSDN博客 个人专栏: 【数据结构初阶】 &#x1f4d8; 基础数据结构【C语言】 &#x1f4bb; C语言编程技巧【C】 &#x1f680; 进阶C【OJ题解】 &#x1f4dd; 题解精讲 目录 前言&#x1f4cc; 1. 优先级队列、容器适配器和 deque 概述✨1.1 什么是优…

SpringMVC学习笔记(一)

一、SpringMVC的基本概念 &#xff08;一&#xff09;三层架构和MVC 1、三层架构概述 我们的开发架构一般都是基于两种形式&#xff0c;一种是 C/S 架构&#xff0c;也就是客户端/服务器&#xff0c;另一种是 B/S 架构&#xff0c;也就是浏览器服务器。在 JavaEE 开发中&…

Jav项目实战II基于微信小程序的助农扶贫的设计与实现(开发文档+数据库+源码)

目录 一、前言 二、技术介绍 三、系统实现 四、文档参考 五、核心代码 六、源码获取 全栈码农以及毕业设计实战开发&#xff0c;CSDN平台Java领域新星创作者&#xff0c;专注于大学生项目实战开发、讲解和毕业答疑辅导。获取源码联系方式请查看文末 一、前言 在当前社会…

Ubuntu安装ollama,并运行ollama和通义千问,使用gradio做界面

Ubuntu安装ollama&#xff0c;并运行ollama和通义千问 安装ollama方式一&#xff1a;方式二 下载安装模型运行大模型运行ollama服务前端的实现python环境安装修改pip国内源前端页面搭建测试前后端联通设计完整的ui 安装ollama 方式一&#xff1a; 访问网站连接&#xff0c;选…

对接阿里云实人认证

对接阿里云实人认证-身份二要素核验接口整理 目录 应用场景 接口文档 接口信息 请求参数 响应参数 调试 阿里云openApi平台调试 查看调用结果 查看SDK示例 下载SDK 遇到问题 本地调试 总结 应用场景 项目有一个提现的场景&#xff0c;需要用户真实的身份信息。 …

C++ 的发展

目录 C 的发展总结&#xff1a;​编辑 1. C 的早期发展&#xff08;1979-1985&#xff09; 2. C 标准化过程&#xff08;1985-1998&#xff09; 3. C 标准演化&#xff08;2003-2011&#xff09; 4. C11&#xff08;2011年&#xff09; 5. C14&#xff08;2014年&#xf…