惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Latest news
Latest news
T
Troy Hunt's Blog
V
Vulnerabilities – Threatpost
L
LINUX DO - 热门话题
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
Simon Willison's Weblog
Simon Willison's Weblog
V
V2EX
博客园 - 司徒正美
B
Blog RSS Feed
AWS News Blog
AWS News Blog
MyScale Blog
MyScale Blog
Scott Helme
Scott Helme
Cisco Talos Blog
Cisco Talos Blog
Last Week in AI
Last Week in AI
NISL@THU
NISL@THU
博客园 - Franky
P
Proofpoint News Feed
博客园_首页
C
CERT Recently Published Vulnerability Notes
雷峰网
雷峰网
S
Schneier on Security
P
Proofpoint News Feed
Hugging Face - Blog
Hugging Face - Blog
G
GRAHAM CLULEY
博客园 - 三生石上(FineUI控件)
月光博客
月光博客
WordPress大学
WordPress大学
The Hacker News
The Hacker News
T
Threatpost
阮一峰的网络日志
阮一峰的网络日志
A
Arctic Wolf
Microsoft Azure Blog
Microsoft Azure Blog
T
The Exploit Database - CXSecurity.com
Engineering at Meta
Engineering at Meta
罗磊的独立博客
T
The Blog of Author Tim Ferriss
D
Darknet – Hacking Tools, Hacker News & Cyber Security
I
Intezer
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
K
Kaspersky official blog
SecWiki News
SecWiki News
云风的 BLOG
云风的 BLOG
美团技术团队
C
Cybersecurity and Infrastructure Security Agency CISA
博客园 - 【当耐特】
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
Security Latest
Security Latest
C
Cyber Attacks, Cyber Crime and Cyber Security
B
Blog
S
Security Affairs

博客园 - 张占岭

apisix~OpenResty各阶段的介绍 keycloak~aud受众字段的作用及如何生成 wso2~关于workbuddy中mcp在wso2中的授权端点 k8s~避免调度资源碎片化 WEB安全~csrf介绍 WEB安全~DPoP的介绍 WEB安全~csp的介绍 什么是中间人攻击 WEB安全~xss的介绍 k8s~pod资源限制和JVM的XMX配置 关于对wso2和keycloak的token交换的调研 keycloak~实现OAuth 2.0 Token Exchange backstage~实体的介绍及它们的关系 backstage~openapi的接入与protobuf的对比 backstage~将java服务添加到backstage backstage~对接github和gitlab backstage~开始一个backstage应用 apisix~graphQL的支持 wso2几个核心项目介绍 docker~BuildKit的介绍 k8s~secret资源的使用 算法~时间戳计算两个日期是否为同天同时同分 wso2~4.5升级到4.6需要更新的数据表 backstage~Backstage的概述 springboot~jpa优雅的软删除能力 springboot~ImportBeanDefinitionRegistrar在自定义RPC框架中的使用 keycloak~深入了解DefaultSegmentedDataContainer对象解决内存泄漏 keycloak~分布式部署中会话过期清理机制 wso2~通过三方IDP的token置换wso2的token jmeter进行接口压测 Keycloak~infinispan中MergedUpdate中lifespanMs和maxIdleTimeMs wso2~添加mcp服务的注意点
springboot~关于构造方法注入和字段注入的选择
张占岭 · 2026-07-02 · via 博客园 - 张占岭

在 Spring Boot 开发中,强烈推荐使用第一种方式(构造器注入 + @RequiredArgsConstructor),而不是第二种(字段注入 + @Autowired)。这不仅是 Spring 官方的最佳实践,也是现代 Java 开发的主流共识。


✅ 第一种方式(构造器注入)的优势

@RestController
@RequiredArgsConstructor
public class PlatformUserTokenController {
    private final PlatformUserTokenService platformUserTokenService;
    private final PortalUserContext userContext;
    private final McpPlatformUserTokenRepository mcpPlatformUserTokenRepository;
}

1. 不可变性(Immutability)

  • 使用 final 修饰的字段,在对象创建后不能被修改,保证了依赖的不可变性
  • 这有助于编写线程安全的代码,避免因意外重新赋值导致的 bug。

2. 依赖明确,便于单元测试

  • 构造器注入使得依赖关系在类的外部是显式的,测试时可以直接通过构造器传入 Mock 对象,无需依赖 Spring 容器。
  • 例如:
    new PlatformUserTokenController(mockService, mockContext, mockRepository);
    
  • 而字段注入需要借助 Spring 的 ReflectionTestUtils@MockBean,测试代码更复杂且不直观。

3. Null 安全

  • 构造器注入强制要求所有依赖在对象实例化时提供,如果 Spring 容器中缺少某个 Bean,启动时会立即失败(抛出 BeanCreationException),而不是在运行时才出现 NullPointerException
  • 字段注入则可能因为未注入而留下 null,导致运行时意外错误。

4. 避免循环依赖

  • 构造器注入能够提前检测循环依赖(Spring 会抛出 BeanCurrentlyInCreationException),而字段注入则可能隐藏循环依赖,直到运行时才暴露,且解决起来更困难。

5. 更好的代码可读性和设计

  • 构造器注入清晰地表明了该类“必须拥有”的依赖,符合面向对象的设计原则(依赖通过构造函数显式声明)。
  • 同时,构造器注入也方便 IDE 自动生成、重构,以及静态代码分析工具检测未使用的依赖。

6. Lombok 简化样板代码

  • @RequiredArgsConstructor 自动生成包含所有 final 字段的构造器,省去了手写构造器的繁琐,既简洁又保持了上述所有优势。

❌ 第二种方式(字段注入)的缺陷

@RestController
public class PlatformUserTokenController {
    @Autowired
    private PlatformUserTokenService platformUserTokenService;
    // ...
}

1. 不可测试性

  • 测试时只能通过 Spring 容器启动或借助 ReflectionTestUtils 设置字段,导致测试变得笨重且与 Spring 耦合。

2. NPE 风险

  • 字段注入可能因为配置错误导致依赖未被注入,对象仍能被创建(因为无参构造器存在),后续调用时抛出 NullPointerException,问题被延迟到运行时。

3. 对 Spring 容器强依赖

  • 类本身无法脱离 Spring 容器独立使用(例如在普通 Java 程序中),降低了可复用性。

4. 循环依赖隐患

  • 字段注入允许循环依赖存在(Spring 通过三级缓存解决),但这会掩盖设计问题,增加维护难度。

5. 代码可读性差

  • 依赖关系散落在字段声明中,不如构造器一目了然。

📌 结论与最佳实践

  • 推荐:始终使用构造器注入(方式一),配合 Lombok 的 @RequiredArgsConstructor 或手动编写构造器。这正是 Spring 官方在文档中强烈建议的方式(参见 Spring 官方文档 中关于“基于构造器的依赖注入”的推荐)。

  • 例外场景:在极少数情况下(例如需要注入非必要依赖,或存在循环依赖的遗留代码),才考虑使用字段注入或 Setter 注入,但这属于临时妥协,应从设计层面重构。

总之,方式一是更现代、更健壮、更优雅的选择,理应成为团队编码规范中的标准实践。