当前位置: 首页 > news >正文

【Spring属性注入】构造器注入 vs 字段注入

1. 最佳实践:构造器注入 vs 字段注入

在 Spring 中,构造器注入(Constructor Injection) 是官方推荐的最佳实践,而 字段注入(Field Injection)@Resource 通常不推荐,原因如下:

对比项构造器注入 (@RequiredArgsConstructor)字段注入 (@Resource)
依赖不可变性✅ 依赖为 final,不可变,线程安全❌ 依赖可变,可能被意外修改
单元测试友好性✅ 可直接通过构造器传入 Mock 对象❌ 需要反射或 Spring 容器,测试复杂
循环依赖检测✅ 编译时即可发现循环依赖❌ 运行时才能发现循环依赖
代码可读性✅ 明确声明所有必需依赖❌ 依赖隐藏在字段中,难以识别
Spring 官方推荐✅ 官方推荐❌ 不推荐

结论:优先使用 构造器注入(即 @RequiredArgsConstructor + private final)。


2. 为何 @RequiredArgsConstructor 需要 new

问题出在 接口无法直接实例化。以下是具体原因:

错误场景分析:
@RequiredArgsConstructor
public class MyService {
    private final IJCmsMediaImageRelevanceService mediaImageRelevanceService; 

    // 错误:尝试 new 接口
    public void someMethod() {
        IJCmsMediaImageRelevanceService service = new IJCmsMediaImageRelevanceService(); // ❌ 编译错误
    }
}
  • 接口无法实例化IJCmsMediaImageRelevanceService 是一个接口,不能直接 new
  • Spring 依赖管理@RequiredArgsConstructor 生成的构造器需要 Spring 自动注入接口的实现类(即 Bean)。如果 Spring 容器中没有该接口的实现类,会导致注入失败。
为什么 @Resource 看似可以 “new”?
  • @Resource 是字段注入,它的依赖解析由 Spring 容器在运行时完成。你看到的 “可以 new” 是误解,实际是 Spring 自动代理了接口并注入实现类。
  • 如果在非 Spring 环境中手动 new 一个依赖 @Resource 的类,字段注入会失败,因为 Spring 未介入。

3. 正确解决依赖注入问题
步骤 1:确保接口有实现类并被 Spring 管理
// 接口
public interface IJCmsMediaImageRelevanceService {
    // 方法定义
}

// 实现类
@Service // 关键:标记为 Spring Bean
public class JCmsMediaImageRelevanceServiceImpl implements IJCmsMediaImageRelevanceService {
    // 实现方法
}
步骤 2:使用构造器注入
@RequiredArgsConstructor
public class MyService {
    private final IJCmsMediaImageRelevanceService mediaImageRelevanceService; // ✅ Spring 自动注入实现类

    // 无需手动 new,Spring 会自动注入 JCmsMediaImageRelevanceServiceImpl 实例
}
步骤 3:验证 Spring 配置
  • 确保实现类所在的包被 Spring 扫描到:
    @SpringBootApplication
    @ComponentScan("com.yourpackage.implementations") // 指定扫描路径
    public class Application {
        public static void main(String[] args) {
            SpringApplication.run(Application.class, args);
        }
    }
    

关键总结:

  1. 优先使用构造器注入@RequiredArgsConstructor + private final),符合 Spring 最佳实践。
  2. 接口无法直接实例化,必须通过 Spring 注入其实现类。
  3. 确保所有依赖接口的实现类被标记为 @Service@Component 等,并被 Spring 扫描到。

相关文章:

  • 企业知识管理的网络构建与优化路径探析
  • 【前端框架】Vue3 面试题深度解析
  • 利用ollama本地部署deepseek
  • Linux操作系统4-进程间通信3(基于管道的进程池设计)
  • Cython学习笔记1:利用Cython加速Python运行速度
  • 2025年信息科学与工程学院科协单片机编程介绍——按键拓展编程
  • 第6章:基于LangChain如何开发Agents,附带客户支持智能体示例
  • Spring Boot 中多线程工具类的配置与使用:基于 YAML 配置文件
  • 21.回溯算法3
  • 【2025最新版】Chrome谷歌浏览器如何能恢复到之前的旧版本
  • 【信息系统项目管理师-案例真题】2013下半年案例分析答案和详解
  • 对CSS了解哪些?
  • Ubuntu 下 nginx-1.24.0 源码分析 - ngx_os_specific_init函数
  • 网站改了域名,如何查找?
  • HTTP和HTTPS详解
  • ai json处理提示词
  • AI大模型零基础学习(7):边缘智能与物联网——让AI走出云端
  • XML XML约束 二、DTD
  • 基于STM32的智能工业设备健康监测系统
  • StableDiffusion学习笔记——6、XYZ图表
  • 大理洱源4.8级地震致442户房屋受损,无人员伤亡
  • 人民日报开新栏,冼星海之女追忆父亲创作《黄河大合唱》
  • 人民日报:外资车企携新车、前沿技术亮相上海车展,坚定信心深耕中国市场
  • 稀土管制难倒特斯拉人形机器人“擎天柱”,马斯克:“正与中国协商”
  • 上海市统计局:经济运行开局平稳,高质量发展扎实推进
  • 巴基斯坦航天员选拔工作正在进行,1人将以载荷专家身份参加联合飞行