跳到主要内容
极客日志极客日志
首页博客AI提示词GitHub精选代理工具
搜索
|注册
博客列表
Javajava

Spring IoC 容器与依赖注入核心机制详解

Spring IoC 容器管理 Bean 的生命周期与依赖关系。Bean 名称生成遵循类名小驼峰或全大写规则,方法级@Bean 则直接使用方法名。支持通过@ComponentScan 自定义扫描路径,默认包含启动类包及子包。依赖注入主要包含构造器、Setter 及字段注入三种方式,其中构造器注入为官方推荐方案。当存在多个同类型 Bean 时,可通过@Primary、@Qualifier 或@Resource 注解解决冲突,@Autowired 按类型注入,@Resource 按名称注入。

嘘发布于 2026/3/21更新于 2026/4/293 浏览
Spring IoC 容器与依赖注入核心机制详解

Bean 名称生成规则

在 Spring 框架中,Bean 的名称决定了我们在容器中如何获取它。理解命名规则是避免冲突的关键。

类注解生成的 Bean 名称

当使用 @Component、@Service 等注解时,Spring 会根据类名自动生成 Bean 名称:

  • 情况 1:类名前两个字母都是大写 → Bean 名称直接等于类名本身。
    • 例:class HTTPClient {} → Bean 名称为 HTTPClient
  • 情况 2:其他情况 → Bean 名称是类名的小驼峰写法(首字母小写)。
    • 例:class UserService {} → Bean 名称为 userService

@Bean 注解的 Bean 名称

在配置类中使用 @Bean 标注方法时,Bean 名称直接等于方法名。

@Bean
public UserService userService() {
    return new UserService();
}

此时 Bean 名称即为 userService。

如果想自定义 Bean 名称,可以直接在注解中指定:

@Bean(name = "myOrderDao")
public OrderDao orderDao() { return new OrderDao(); }

或者简写为:

@Bean("u1")
public User user1(){ 
    User user = new User(); 
    user.setName("zhangsan"); 
    user.setAge(18); 
    return user; 
}

这样既可以通过 user1 也可以通过 u1 获取对象。

定义多个同类型对象

同一个类可以定义多个对象,常见于多数据源场景。但要注意,如果通过类型获取,Spring 会报错提示存在多个匹配项。

@Component
public class BeanConfig {
    @Bean
    public User user1(){ 
        User user = new User(); 
        user.setName("zhangsan"); 
        user.setAge(18); 
        return user; 
    }
    @Bean
    public User user2(){ 
        User user = new User(); 
        user.setName("lisi"); 
        user.setAge(19); 
        return user; 
    }
}

运行后尝试通过类型获取:

ApplicationContext context = SpringApplication.run(SpringIocDemoApplication.class, args);
User user = context.getBean(User.class); // 这里会抛出异常

报错信息通常提示期望只有一个匹配,结果发现了多个。此时需要根据 Bean 名称来获取:

User user1 = (User) context.getBean("user1");
User user2 = (User) context.getBean("user2");
System.out.println(user1);
System.out.println(user2);

组件扫描路径控制

使用 @Component 等注解声明的 Bean 不一定都会生效,前提是它们必须被 Spring 扫描到。

默认扫描范围

Spring Boot 的 @SpringBootApplication 已包含 @ComponentScan,默认扫描启动类所在的包及其所有子包。因此,只要把 Bean 放在启动类包或子目录下,无需额外配置即可生效。

手动配置扫描

如果遇到以下情况,需要手动添加 @ComponentScan:

  1. Bean 所在的包不在启动类的包或子包下。
  2. 想精确控制扫描范围(例如只扫描 service 和 controller 包)。
  3. 想排除某些不想被扫描的类。

基础用法示例:

@ComponentScan({"com.example.service", "com.example.controller"})
@SpringBootApplication
public class SpringIocDemoApplication {
    public static void main(String[] args) {
        ApplicationContext context = SpringApplication.run(SpringIocDemoApplication.class, args);
    }
}

进阶用法支持包含或排除特定类:

@ComponentScan(
    basePackages = "com.example",
    excludeFilters = @ComponentScan.Filter(
        type = FilterType.ASSIGNABLE_TYPE,
        classes = UserService.class
    )
)
@SpringBootApplication
public class SpringIocDemoApplication {
    // ...
}

注意:配置类上的 @Configuration 标记也需要被扫描到,否则其中的 @Bean 方法不会被执行。

依赖注入方式详解

依赖注入(DI)是 IoC 容器创建 Bean 时提供依赖资源的过程。Spring 主要提供三种注入方式。

1. 属性注入(Field Injection)

通过 @Autowired 注解直接作用于字段。

@Controller
public class UserController {
    @Autowired
    private UserService userService;
    
    public void sayHi(){
        userService.sayHi();
    }
}

优点简洁,缺点是无法注入 final 修饰的属性,且容易在使用前出现空指针异常。

2. 构造方法注入(Constructor Injection)

在构造方法中实现注入,这是 Spring 4.X 之后官方推荐的方式。

@Controller
public class UserController2 {
    private final UserService userService;
    
    @Autowired
    public UserController2(UserService userService) {
        this.userService = userService;
    }
}

如果类只有一个构造方法,@Autowired 可以省略。这种方式能保证依赖对象在使用前完全初始化,且支持 final 属性。

3. Setter 注入(Setter Injection)

通过 Setter 方法注入,需在方法上添加 @Autowired。

@Controller
public class UserController3 {
    private UserService userService;
    
    @Autowired
    public void setUserService(UserService userService) {
        this.userService = userService;
    }
}

适合需要在实例化后重新配置的场景,但注入对象可能被修改。

解决注入冲突

当同一类型存在多个 Bean 时,直接使用 @Autowired 会报错。Spring 提供了以下几种解决方案:

使用 @Primary

指定某个 Bean 为默认实现。

@Component
public class BeanConfig {
    @Primary
    @Bean("u1")
    public User user1(){ /* ... */ }
    @Bean
    public User user2(){ /* ... */ }
}

使用 @Qualifier

配合 @Autowired 指定具体的 Bean 名称。

@Autowired
@Qualifier("user2")
private User user;

使用 @Resource

JDK 提供的注解,默认按名称注入。

@Resource(name = "user2")
private User user;

@Autowired 与 @Resource 的区别

特性@Autowired@Resource
来源Spring 框架JDK (Java EE)
默认注入方式按类型 (byType)按名称 (byName)
指定名称需配合 @Qualifier直接用 name 属性
兼容性仅 Spring 容器通用,兼容所有 Java EE 容器

在实际开发中,若项目仅使用 Spring 生态,推荐优先用 @Autowired + @Qualifier;若需跨容器兼容,可考虑 @Resource。

目录

  1. Bean 名称生成规则
  2. 类注解生成的 Bean 名称
  3. @Bean 注解的 Bean 名称
  4. 定义多个同类型对象
  5. 组件扫描路径控制
  6. 默认扫描范围
  7. 手动配置扫描
  8. 依赖注入方式详解
  9. 1. 属性注入(Field Injection)
  10. 2. 构造方法注入(Constructor Injection)
  11. 3. Setter 注入(Setter Injection)
  12. 解决注入冲突
  13. 使用 @Primary
  14. 使用 @Qualifier
  15. 使用 @Resource
  16. @Autowired 与 @Resource 的区别
  • 💰 8折买阿里云服务器限时8折了解详情
  • GPT-5.5 超高智商模型1元抵1刀ChatGPT中转购买
  • 代充Chatgpt Plus/pro 帐号了解详情
  • 🤖 一键搭建Deepseek满血版了解详情
  • 一键打造专属AI 智能体了解详情
极客日志微信公众号二维码

微信扫一扫,关注极客日志

微信公众号「极客日志V2」,在微信中扫描左侧二维码关注。展示文案:极客日志V2 zeeklog

更多推荐文章

查看全部
  • 鸿蒙 Next 应用配置文件
  • Buzz 离线语音转文字工具:Whisper 模型集成与使用指南
  • 如何降低 AIGC 检测率:15 个提示词优化写作风格
  • C++入门知识(三):引用、内联函数与 nullptr 概念详解
  • 前缀和算法详解与实战应用
  • FPGA 深入解析 M25P16 SPI-FLASH 读写操作与 Verilog 实现
  • 前端大数据导出优化:解决 Chrome 内存崩溃的实战方案
  • FPGA 开发常用软件对比:Vivado、Quartus、ModelSim 详解
  • Llama-Factory 支持 Flash Attention 吗?训练加速配置详解
  • 2025 年 AI 产品经理职业发展路径与核心能力解析
  • Python 音乐下载工具 Musicdl 多平台支持使用指南
  • Spring Web 模块核心概念与基础架构解析
  • C++11 右值引用与移动语义详解:从性能瓶颈到零拷贝优化
  • Oracle WebLogic 代理插件未授权 RCE 漏洞检测与分析
  • 前端实战:实现浏览器通知功能
  • 2026 年 3 月大模型全景解析:国产登顶、百万上下文与 Agent 工业化
  • Visual C++ 运行库修复指南:解决 Windows 程序兼容问题
  • 使用 Copilot 制定 60 天 AI 学习计划并同步至 Outlook 日程
  • 第十三届蓝桥杯大赛软件赛省赛 C/C++ 大学 B 组题解
  • 前端 CI/CD 流程与自动化部署实践

相关免费在线工具

  • Keycode 信息

    查找任何按下的键的javascript键代码、代码、位置和修饰符。 在线工具,Keycode 信息在线工具,online

  • Escape 与 Native 编解码

    JavaScript 字符串转义/反转义;Java 风格 \uXXXX(Native2Ascii)编码与解码。 在线工具,Escape 与 Native 编解码在线工具,online

  • JavaScript / HTML 格式化

    使用 Prettier 在浏览器内格式化 JavaScript 或 HTML 片段。 在线工具,JavaScript / HTML 格式化在线工具,online

  • JavaScript 压缩与混淆

    Terser 压缩、变量名混淆,或 javascript-obfuscator 高强度混淆(体积会增大)。 在线工具,JavaScript 压缩与混淆在线工具,online

  • Base64 字符串编码/解码

    将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online

  • Base64 文件转换器

    将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online