Spring IoC 入门详解:Bean 注册、注解使用与 @ComponentScan 配置

目录

一、什么是 Spring IoC?

1. 先搞懂:IoC是什么

IoC 全称 Inversion of Control (控制反转) ,咱先不说Spring IOC概念,我们首先按照字面意思给你举个生活的例子来对比一下

假设你要装一套新房:

方式1在没有IOC下:你就是业主,要亲手搞定所有事情,做的事情包括不限于:自己找工人,自己买材料,自己管流程,自己扛风险

方式2在IOC下:你只需要做 2 件事,告诉装修公司需求:比如说我要简约风格、预算 30 万、3 个月完工。最后验收房子:装修公司把所有细节搞定,你直接拎包入住,剩下的所有事,全由装修公司负责,找工人、买材料等等

这就是控制权反转 ------ 原本由业主掌控的工人招聘、材料采购、流程管理的权力,反转给了装修公司(Spring IoC 容器 )。你不再管细节,只关心最终需求结果验收

所以控制反转就是控制权反转,而 Spring IoC 的核心就是反转控制权 :将对象的创建、依赖(DI)的注入、生命周期 的管理全部交给 Spring 容器负责,开发者不再手动控制

2.Spring IoC 容器:IoC 的 "执行者"

Spring IoC 容器 是实现 IoC 思想的核心载体,如果 Spring IOC 是个思想 ,那Spring IOC容器 就是这个思想的具体实现工具或载体 ,当需要某个对象时,创建对象的任务交给容器, 程序中只需要依赖注⼊(DependencyInjection,DI)就可以了,其实笼统的来说Spring是⼀个IoC容器,所以有时Spring也称为Spring容器

二、Bean 的存储

Bean 的存储核心是 Spring 容器(IoC 容器) 对对象的 "注册 - 实例化 - 管理" 过程 ,本质是将 Bean 的元数据(类信息、依赖、配置)注册到容器,再由容器根据规则创建实例并存储,供后续依赖注入或直接获取,简单的说将对象的控制权交给Spring的IOC容器,由IOC容器创建及管理对象就是Bean的存储

1. 注解驱动

要让 Spring 容器存储 Bean,首先需要通过某种方式定义 Bean(即告诉 Spring "哪个类需要被管理"),这种方式之一就是注解,Spring框架为此提供了更丰富的注解
共有两类注解类型可以实现:

  1. 类注解:@Controller、@Service、@Repository、@Component、@Configuration
  2. 方法注解:@Bean

@Controller(控制器存储)

从Spring容器中获取对象

获得对象后,调用print方法,测试结果为HelloController对象中的print方法的打印结果

那如果把@Controller删掉呢?

结合上述结果可以得知: @Controller 所标识的类会被 Spring 容器注册为 Bean,也就是将控制权反转给了Spring管理 ,从而可以能从Spring中获取到Controller对象来使用

获取bean对象的其他⽅式

主要为三次方式:

  1. 根据类型获得Bean
  2. 根据Bean名称和类型获得Bean
  3. 根据Bean名称获得Bean

什么是bean名?

Spring bean是Spring框架在运⾏时管理的对象,Spring会给管理的对象起⼀个名字.⽐如学校管理学⽣,会给每个学⽣分配⼀个学号,根据学号,就可以找到对应的学⽣.Spring也是如此,给每个对象起⼀个名字,根据Bean的名称(BeanId)就可以获取到对应的对象

怎么知道bean名为什么?

如何知道bean名为什么,这一点在spring 官方文档中有详细说明

程序开发⼈员不需要为bean指定名称(BeanId),如果没有显式的提供名称(BeanId),Spring容器将为该bean⽣成唯⼀的名称.

命名约定使⽤Java标准约定作为实例字段名.bean名称以⼩写字⺟开头(当第⼀个和第⼆个字符都是⼤写时,将保留原始的⼤⼩写),然后使⽤驼峰式大小写,也就是说在此处HelloerController的bean名为helloController,但是注意此处的getBean为object类性,需要强制转换到对应的bean对象类型

2. 类注解总结

其实这些注解本质都是 @Component 的 "派生注解" ,这些类注解的存在是为了明确类的职责分层 ,让代码更具可读性,Spring 扫描时会将它们统一识别为 Bean 并纳入容器管理,只是在 "语义" 和 "附加功能" 上做了区分。

源码:

从源码中可知并无太大区别

"语义" 和 "附加功能"区别

注解 "语义" 和 "附加功能"
@Component 通用组件
@Controller 控制层,接收请求,对请求进⾏处理,并进⾏响应
@Servie 业务逻辑层,处理具体的业务逻辑
@Repository 数据访问层,也称为持久层.负责数据访问操作
@Configuration 配置层.处理项⽬中的⼀些配置信息.

注意:

这5个注解, @Controler不可以和其他注解替换,在控制层中必须要使用@Controller

在不固定场景下,控制层使用@Service也可能能访问成功

3. ⽅法注解@Bean

上述所说的注解是添加到某个类上的类注解,但是存在两个问题:

  1. 外部依赖包中的类,无法手动为其添加类注解
  2. 同一个类需要创建多个实例(比如多个不同配置的数据源)

这种场景, 我们就需要使⽤⽅法注解@Bean

⽅法注解@Bean的使⽤



测试结果:

@Bean 必须搭配五大注解类使用,否则无法被 Spring 扫描识别,提示错误

定义多个对象

一个 @Bean 方法对应一个 Bean 实例,在同一个类中,通过编写多个 @Bean 方法,即可注册多个对象到 Spring 容器

测试结果:

为什么这里我直接使用BeanName而不直接Student类呢,核心原因就是:同一类型有多个 Bean时,按类型获取会报错(Spring 无法确定选定的是s1,还是s2),而容器中 Bean 名称是唯一的

@Bean注解的bean,bean的名称就是它的⽅法名

当@Bean方法中传参

java 复制代码
String name="hr";
    @Bean
    public Student s1(String name){
       return  new Student(name,1);
    }

Spring 会从Spring容器当中, 查找String类型的对象,赋值给name

@Bean的重命名

@Bean 的重命名本质是通过注解的 name 或 value 属性 自定义 Bean 的名称,替代默认的方法名作为 Bean 在 Spring 容器中的标识。

name 和 value 属性完全等价

测试结果:

这里就是通过重命名student1,student2来代替s1方法名

三、扫描路径

在刚刚开始搭建spring boot的时候,我们有学到过默认扫描的范围是SpringBoot启动类所在包及其⼦包的@controller,但是随着我们深入学习,难道这个范围就是固定的吗,显然不是,这就引入了 @ComponentScan注解

@ComponentScan

@ComponentScan就是告诉 Spring:"从这些包路径下,查找并加载所有带候选注解的类,将它们注册为 Bean"

操作@ComponentScan来更改扫描的范围

测试结果:

四、最后再说一下

总结一下,本篇IOC内容就一句话 "注解定标识,扫描定范围,@Bean 补灵活 ",还有本篇文章没有怎么提及依赖(DI)的内容,在Spring IOC中IOC和DI是 "目标 - 手段" 的统一关系,对应DI的理解也同样很重要,下篇文章将重点讲解

相关推荐
3GPP仿真实验室几秒前
【Matlab源码】6G候选波形:OFDM-IM 增强仿真平台 DM、CI
开发语言·matlab·ci/cd
devmoon4 分钟前
在 Polkadot 上部署独立区块链Paseo 测试网实战部署指南
开发语言·安全·区块链·polkadot·erc-20·测试网·独立链
lili-felicity4 分钟前
CANN流水线并行推理与资源调度优化
开发语言·人工智能
爬山算法5 分钟前
Hibernate(87)如何在安全测试中使用Hibernate?
java·后端·hibernate
沐知全栈开发5 分钟前
CSS3 边框:全面解析与实战技巧
开发语言
island131415 分钟前
CANN GE(图引擎)深度解析:计算图优化管线、内存静态规划与异构 Stream 调度机制
c语言·开发语言·神经网络
云姜.17 分钟前
线程和进程的关系
java·linux·jvm
是码龙不是码农19 分钟前
支付防重复下单|5 种幂等性设计方案(从初级到架构级)
java·架构·幂等性
曹牧19 分钟前
Spring Boot:如何在Java Controller中处理POST请求?
java·开发语言
heartbeat..19 分钟前
JVM 性能调优流程实战:从开发规范到生产应急排查
java·运维·jvm·性能优化·设计规范