Spring学习 (一): IoC容器

前言

参考
廖雪峰Spring教程

一、什么是IoC容器

容器的意思可以理解为一个提供供程序正常运行,提供各种依赖的组件的包的环境。

IoC,控制反转,实际上就是将原本由代码编写者控制的各个对象(组件)的生命周期托管给底层的容器,应用层不需要一个个定义好什么时候初始化,什么时候析构释放,所有组件不再由应用程序自己创建和配置,而是由IoC容器负责,这样,应用程序只需要直接使用已经创建好并且配置好的组件。为了能让组件在IoC容器中被“装配”出来,需要某种“注入”机制。

什么是注入呢,假设类A中存在成员类B,这个B可以通过A的setter方式实例化,即依赖的函数提供setter的注入接口,然后coder需要在外部定义好依赖关系(xml文件)/或者通过注解,然后让IoC自己解析并创建依赖的各个组件

在设计上,Spring的IoC容器是一个高度可扩展的无侵入容器。所谓无侵入,是指应用程序的组件无需实现Spring的特定接口,或者说,组件根本不知道自己在Spring的容器中运行。这种无侵入的设计有以下好处:1. 应用程序组件既可以在Spring的IoC容器中运行,也可以自己编写代码自行组装配置;2. 测试的时候并不依赖Spring容器,可单独进行测试,大大提高了开发效率


二、装配Bean

什么是Bean? 简单理解就是需要被托管的组件

可以看以下代码,

public class MailService {public void sendLoginMail(User user) {}public void sendRegisterMail(User user) {}
}/***********************************************************/
public class UserService {private MailService mailService;public void setMailService(MailService mailService) {this.mailService = mailService;}private List<User> users;public User login(String email, String password) {for (User user : users) {if (user.getEmail().equalsIgnoreCase(email) && user.getPassword().equals(password)) {mailService.sendLoginMail(user);return user;}}}public User getUser(long id) {//do something}public User register(String email, String password, String name) {users.forEach((user) -> {if (user.getEmail().equalsIgnoreCase(email)) {throw new RuntimeException("email exist.");}});User user = new User(users.stream().mapToLong(u -> u.getId()).max().getAsLong() + 1, email, password, name);users.add(user);mailService.sendRegistrationMail(user);return user;}
}

UserService依赖MailService的两个函数,实际设置mailService时,通过设置setter搞定,IoC接口通过这个setter方法完成注入,但需要额外信息从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/beanshttps://www.springframework.org/schema/beans/spring-beans.xsd"><bean id="userService" class="com.itranswarp.learnjava.service.UserService"><property name="mailService" ref="mailService" /></bean><bean id="mailService" class="com.itranswarp.learnjava.service.MailService" />
</beans>
  • 每个<bean …>都有一个id标识,相当于Bean的唯一ID;
  • 在userServiceBean中,通过注入了另一个Bean;
  • Bean的顺序不重要,Spring根据依赖关系会自动正确初始化

然后创建IoC实例,加载配置文件,让Spring容器为我们创建并装配好配置文件中指定的所有Bean

ApplicationContext context = new ClassPathXmlApplicationContext("application.xml");
// 获取Bean:
UserService userService = context.getBean(UserService.class);
// 正常调用:
User user = userService.login("bob@example.com", "password");

三、使用注解

使用注解则可以直接不用再写繁琐的XML文件了,常用的注解组合有@Component @Autowired@Configuration @Bean

@Component 注解用于将一个类标记为组件(Component),表示它将被Spring容器实例化为一个Bean,就等同于XML中的bean 标签;@Autowired注解用于在需要依赖注入的地方标记,以实现自动装配。Spring容器会自动在上下文中查找匹配的Bean,并将其注入到被标记的字段、构造函数或方法参数中,对应bean下面的property标签。

用法如下

@Component
public class MyBean {private AnotherBean anotherBean;@Autowiredpublic MyBean(AnotherBean anotherBean) {this.anotherBean = anotherBean;}@Autowiredpublic void setAnotherBean(AnotherBean anotherBean) {this.anotherBean = anotherBean;}// ...
}

在这个示例中,MyBean 类中的 anotherBean 字段和 setAnotherBean() 方法都被标记为 @Autowired,表示它们需要被自动装配。Spring容器会自动查找匹配类型的Bean,并将其注入到这些位置。除了字段和方法参数,还可以在构造函数上使用 @Autowired 注解,以实现构造函数注入。

当在一个类中使用 @Autowired 注解标记一个字段、方法或构造函数时,底层的IOC容器会负责实例化这个类,并自动注入所需的依赖项。具体来说,当一个类被实例化时,IOC容器会检查该类中标记为 @Autowired 的字段、方法或构造函数参数。它会查找与这些依赖项类型匹配的Bean,并将它们自动注入到对应的位置。如果没有找到匹配的Bean,或者存在多个匹配的Bean时,Spring框架会抛出异常,提示依赖项无法自动注入或存在歧义。
如果组件既没有使用 @Autowired 注解标注构造函数,也没有使用 @Autowired 注解标注setter方法,IOC容器将不会自动进行依赖项的注入。在这种情况下,需要自己负责手动实例化依赖项并将其注入到组件中。

当存在多个匹配的Bean时,Spring会抛出 NoUniqueBeanDefinitionException 异常,提示依赖项的注入歧义。因此需要解决这个问题。

@Configuration和@Bean用法代码如下:

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class AppConfig {@Beanpublic MyBean myBean() {return new MyBean();}
}
  • @Configuration 是一个注解,用于标识一个类作为配置类。配置类中可以定义Bean的创建和配置信息,以及其他配置项,如AOP、事务管理等。它表明这个类被用来声明Bean的定义。
  • @Bean 注解用于在配置类中声明一个Bean。通过在一个方法上添加 @Bean 注解,该方法的返回值将被注册为一个Bean,并由Spring容器进行管理。可以通过在 @Configuration 类中的方法上使用 @Bean 注解来创建和配置Bean。(这样子可以让一个返回的对象自动注册为Bean)

当你需要定义和配置多个Bean时,可以使用 @Configuration 注解将一个类标识为配置类。在配置类中,你可以使用 @Bean 注解声明方法,该方法的返回值将被注册为一个Bean。通常,你可以在配置类中进行一些复杂的Bean创建和配置,包括外部依赖的集成、条件化的Bean定义等。
示例场景:创建和配置数据源、声明第三方库的连接器、定义自定义的Bean等。


四、其他注解

  1. @Value:用法@Value(resourcePath),用于注入文件,方便程序读取;@Value("${app.zone:Z}"); @Value("#{smtpConfig.host}")
  2. @Order:用法@Order(Num) 当多个Bean被注入到一个List时,若List中组件存在顺序要求,可以通过@Order指定顺序
  3. @PostConstruct:一个Bean在注入必要的依赖后,需要进行初始化(监听消息等,我们通常会定义一个init()方法进行初始化,用@PostConstruct修饰
  4. @PreDestory:在容器关闭时,有时候还需要清理资源(关闭连接池等)定义一个shutdown()方法进行清理,用@PreDestory修饰
  5. @PropertySource(“app.properties”) :读取以key=value的形式写在.properties文件中的配置
  6. @Profile: 条件装配,用于表示不同环境下的装配, 分为test,native, production三个环境

@Scope
对于Spring容器来说,当我们把一个Bean标记为@Component后,它就会自动为我们创建一个单例(Singleton),即容器初始化时创建Bean,容器关闭前销毁Bean。在容器运行期间,我们调用getBean(Class)获取到的Bean总是同一个实例。

还有一种Bean,我们每次调用getBean(Class),容器都返回一个新的实例,这种Bean称为Prototype(原型),它的生命周期显然和Singleton不同。声明一个Prototype的Bean时,需要添加一个额外的@Scope注解:

@Component
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) // @Scope("prototype")
public class MailSession {...
}

@Bean(Name) || @Qualifier(Name)
默认情况下,对一种类型的Bean,容器只创建一个实例。但有些时候,我们需要对一种类型的Bean创建多个实例。例如,同时连接多个数据库,就必须创建多个DataSource实例。

如果我们在类中创建了多个同类型的Bean:
Spring会报NoUniqueBeanDefinitionException异常,意思是出现了重复的Bean定义。

这个时候,需要给每个Bean添加不同的名字
可以用@Bean(“name”)指定别名,也可以用@Bean+@Qualifier(“name”)指定别名。

@Configuration
@ComponentScan
public class AppConfig {@Bean("z")ZoneId createZoneOfZ() {return ZoneId.of("Z");}@Bean@Qualifier("utc8")ZoneId createZoneOfUTC8() {return ZoneId.of("UTC+08:00");}
}

补充解释

Spring的IoC容器会自动注册标记为 @Component 或其衍生注解的Bean。

当一个类被标记为 @Component、@Service、@Repository、@Controller 等注解之一时,Spring会自动扫描并注册这个类作为一个Bean。这个过程称为组件扫描(Component Scanning),Spring会自动扫描指定的包及其子包,找到所有标记为组件注解的类,并将其实例化并注册到IoC容器中。

通过自动扫描,Spring会根据类的命名约定或自定义的Bean名称规则为这些类创建默认的Bean名称。例如,对于一个标记为 @Component 的类,默认的Bean名称将是类名的首字母小写形式。你也可以通过 @Component(“beanName”) 的方式显式指定Bean的名称。

此外,Spring还支持在XML配置文件中显式地定义Bean的配置信息,无论是通过 @Bean 在 @Configuration 类中进行定义,还是直接在XML配置文件中进行定义。这些显式定义的Bean也会被注册到IoC容器中。

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

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

相关文章

Java手写HashMap及拓展实践

Java手写HashMap 思维导图 #mermaid-svg-liNfjvnThNZyNIWd {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-liNfjvnThNZyNIWd .error-icon{fill:#552222;}#mermaid-svg-liNfjvnThNZyNIWd .error-text{fill:#552222;…

【OJ比赛日历】快周末了,不来一场比赛吗? #09.16-09.22 #12场

CompHub[1] 实时聚合多平台的数据类(Kaggle、天池…)和OJ类(Leetcode、牛客…&#xff09;比赛。本账号会推送最新的比赛消息&#xff0c;欢迎关注&#xff01; 以下信息仅供参考&#xff0c;以比赛官网为准 目录 2023-09-16&#xff08;周六&#xff09; #3场比赛2023-09-17…

【FPGA项目】进阶版沙盘演练——报文收发(报文处理、CDC、CRC)

前言 书接上文【FPGA项目】沙盘演练——基础版报文收发_子墨祭的博客-CSDN博客&#xff0c;前面我们做了基础版的报文收发&#xff0c;相信对逻辑设计有了一定的认知&#xff0c;在此基础上&#xff0c;继续完善一个实际报文收发可能会遇到的一些处理&#xff1a; 报文处理握手…

公交查询系统

目录 需求分析 1 概述 2 课题分析 3 实现功能步骤 4 项目背景 概要设计 1 系统流程图. 2 功能模块. 3 各功能模块 4 数据存储 5 类设计 三、详细设计 1公交线路查询系统用户界面 2公交信息存储模快 3公交信息查询模块 4用户信息输入和输出模块 四、调试分析 五、使用说明 六、…

STM32外部复位IC与看门狗冲突,无法复位问题解决方案

使用STM32H743制作了一款飞控&#xff0c;外部复位IC采用MAX809STR,打板完后&#xff0c;烧录飞控固件后大量板子无法正常启动&#xff0c;怀疑是晶振没有起振或MCU未焊接好&#xff0c;检查后均焊接正常&#xff0c;编写裸机LED定时闪烁验证程序可正常运行。经网上查询资料锁定…

Python 环境搭建,集成开发环境IDE: PyCharm

Python 环境搭建,集成开发环境IDE: PyCharm 一、Python 环境搭建二、Python下载三、Python安装四、环境变量配置五、Python 环境变量六、运行Python1、交互式解释器&#xff1a;2、命令行脚本3、集成开发环境&#xff08;IDE&#xff1a;Integrated Development Environment&am…

Hadoop-Hive

1. hive安装部署 2. hive基础 3. hive高级查询 4. Hive函数及性能优化 1.hive安装部署 解压tar -xvf ./apache-hive-3.1.2-bin.tar.gz -C /opt/soft/ 改名mv apache-hive-3.1.2-bin/ hive312 配置环境变量&#xff1a;vim /etc/profile #hive export HIVE_HOME/opt/soft/hive…

软件测试的基本流程是什么?软件测试流程详细介绍

软件测试和软件开发一样&#xff0c;是一个比较复杂的工作过程&#xff0c;如果无章法可循&#xff0c;随意进行测试势必会造成测试工作的混乱。为了使测试工作标准化、规范化&#xff0c;并且快速、高效、高质量地完成测试工作&#xff0c;需要制订完整且具体的测试流程。 01…

JavaScript的DOM操作(二)

一、元素的特性attribute 1.元素的属性和特性 前面我们已经学习了如何获取节点&#xff0c;以及节点通常所包含的属性&#xff0c;接下来我们来仔细研究元素Element。 我们知道&#xff0c;一个元素除了有开始标签、结束标签、内容之外&#xff0c;还有很多的属性&#xff0…

Flutter 使用pageview无缝隙自动轮播教程

导入要使用的轮播图片 List<String> imagesa ["assets/images/car_qidian.jpg","assets/images/car_bg.jpg","assets/images/car_bg.jpg","assets/images/car_bg.jpg","assets/images/car_bg.jpg","assets/imag…

【算法与数据结构】450、LeetCode删除二叉搜索树中的节点

文章目录 一、题目二、解法三、完整代码 所有的LeetCode题解索引&#xff0c;可以看这篇文章——【算法和数据结构】LeetCode题解。 一、题目 二、解法 思路分析&#xff1a;本题首先要分析删除节点的五种情况&#xff1a; 1、没有找到节点2、找到节点 左右子树为空左子树为空…

docker容器管理-实操命令

本单元主要是在docker镜像管理下进一步的培训学习文档。 docker镜像管理-实操_忍冬行者的博客-CSDN博客 四.容器管理 1.运行一个容器 docker container run --name c1 -it nginx:latest /bin/sh 2.后台运行一个容器 docker container run --name c1 -it -d nginx:latest 3.查…

微信小程序项目开发Day1

没接触过&#xff0c;直接看视频学习&#xff1a; 千锋教育微信小程序开发制作前端教程&#xff0c;零基础轻松入门玩转微信小程序_哔哩哔哩_bilibili千锋教育微信小程序开发制作前端教程&#xff0c;零基础轻松入门玩转微信小程序共计56条视频&#xff0c;包括&#xff1a;学…

List 获取前N条数据

1.使用for循环遍历 public static void main(String[] args) {int limit 5;List<Integer> oldList Lists.newArrayList(1, 2, 3, 4, 5, 6, 7);List<Integer> newList Lists.newArrayList();if (oldList.size() < limit) {newList.addAll(oldList);return;}fo…

软件工程课件

软件工程 考点概述软件工程概述能力成度模型能力成熟度模型集成软件过程模型逆向工程软件需求需求获取数据流图 需求定义 考点概述 重点章节 软件工程概述 之前老版教程的&#xff0c;之前考过 能力成度模型 记忆 能力等级 和 特点 能力成熟度模型集成 相比于CMM&#xff0c;第…

结合el-input、el-select实现纯前端过滤树形el-table数据

样式图示 1.搜索实现方法 const searchBtn async () > {// 获取table列表数据接口const res await Api.menuList({paging: false})if (res.code 200) {// 把树形结构转成扁平结构let result treeToArray(res.data)// 处理搜索框中数据进行table显示项过滤if(commonData…

分享!JetBrains IDE中的GitLab支持

GitLab是流行的基于git的软件开发和部署平台之一&#xff0c;虽然很长一段时间以来&#xff0c;所有基本git操作都已经可以通过GitLab实现&#xff0c;但GitLab集成仍是JetBrains社区的一大最热门请求。为此&#xff0c;JetBrains团队今年与GitLab联手提供了这种类型的集成。 …

2023年华为杯研究生数学建模竞赛辅导

2023年华为杯研究生数学建模竞赛辅导 各研究生培养单位&#xff1a; 中国研究生数学建模竞赛作为教育部学位管理与研究生教育司指导&#xff0c;中国学位与研究生教育学会、中国科协青少年科技中心主办的“中国研究生创新实践系列大赛”主题赛事之一&#xff0c;是一项面向在校…

使用阿里PAI DSW部署Stable Diffusion WebUI

进入到网址https://pai.console.aliyun.com/里边。 点击创建实例。 把实例名称填写好&#xff0c;选择GPU规格&#xff0c;然后选择实例名称是ecs.gn6v-c8g1.2xlarge。 选择stable-diffusion-webui-env:pytorch1.13-gpu-py310-cu117-ubuntu22.04&#xff0c;然后点击下一步。…

如何利用软文推广进行SEO优化(打造优质软文,提升网站排名)

在当今的互联网时代&#xff0c;SEO优化成为了网站推广的关键。而软文推广作为一种有效的推广方式&#xff0c;其优点不仅仅局限于SEO&#xff0c;还可以带来更多的曝光和用户流量。本文将深入探讨如何做好软文推广&#xff0c;从而提升网站排名和流量。 了解目标受众群体 内容…