spring的注入方式都有什么区别

目录

[1. 构造器注入(Constructor Injection)](#1. 构造器注入(Constructor Injection))

[2. Setter 注入(Setter Injection)](#2. Setter 注入(Setter Injection))

[3. 字段注入(Field Injection)](#3. 字段注入(Field Injection))

[4. 接口注入(Interface Injection)](#4. 接口注入(Interface Injection))

主要区别对比

最佳实践

总结

1. 构造器注入(Constructor Injection)

  • 方式:通过构造方法完成依赖注入。

  • 配置 :

    • XML :使用 <constructor-arg> 标签。
    • Java 注解 :使用 @Autowired 或隐式构造器(Spring 4.3+)。
  • 示例 :

    java

    java 复制代码
    @RequiredArgsConstructor
    public class UserService {
        private final UserRepository userRepository;
    
        // 构造器注入(Spring 4.3+ 可省略 @Autowired)
        /*@Autowired
        public UserService(UserRepository userRepository) {
            this.userRepository = userRepository;
        }*/
    }
  • 特点 :

    • 不可变依赖 :依赖对象在创建后不可变(final 字段)。
    • 强制依赖:对象创建时必须提供所有依赖,避免空指针异常。
    • 防止循环依赖:Spring 会在启动时检测并报错。
  • 适用场景 :

    • 强制依赖的场景(如核心业务组件)。
    • 不可变对象(如使用 final 字段)。

2. Setter 注入(Setter Injection)

  • 方式:通过公共的 Setter 方法完成依赖注入。

  • 配置 :

    • XML :使用 <property> 标签。
    • Java 注解 :使用 @Autowired 或 @Inject。
  • 示例 :

    java

    java 复制代码
    public class UserService {
        private UserRepository userRepository;
    
        // Setter 注入
        @Autowired
        public void setUserRepository(UserRepository userRepository) {
            this.userRepository = userRepository;
        }
    }
  • 特点 :

    • 可选依赖:依赖可以在对象创建后通过 Setter 方法设置。
    • 灵活性高:适合动态修改依赖(如配置参数)。
    • 可能存在空指针风险:需确保使用前依赖已注入。
  • 适用场景 :

    • 可选依赖的场景(如配置参数)。
    • 需要动态修改依赖的场景。

3. 字段注入(Field Injection)

  • 方式:通过反射直接注入私有字段。

  • 配置 :使用 @Autowired、@Resource 或 @Inject 注解。

  • 示例 :

    java

    java 复制代码
    public class UserService {
        @Autowired
        private UserRepository userRepository;
    }
  • 特点 :

    • 代码简洁:无需构造器或 Setter 方法。
    • 依赖隐藏:依赖关系不明确(如无法从构造器看出)。
    • 仅适用于 Spring 容器:不利于单元测试(需使用反射注入)。
  • 适用场景 :

    • 简单组件(如工具类、控制器)。
    • 快速开发或遗留代码。

4. 接口注入(Interface Injection)

  • 方式:通过实现特定接口来声明依赖。

  • 特点 :

    • 侵入性强 :组件需实现 Spring 特定接口(如 ApplicationContextAware)。
    • 已过时:现代 Spring 项目很少使用。
  • 示例 :

    java

    java 复制代码
    public class MyComponent implements ApplicationContextAware {
        private ApplicationContext context;
    
        @Override
        public void setApplicationContext(ApplicationContext context) {
            this.context = context;
        }
    }

主要区别对比

特性 构造器注入 Setter 注入 字段注入
依赖强制性 强制(必须提供) 可选(可后设置) 强制(运行时注入)
不可变性 支持(final 字段) 不支持 不支持
循环依赖检测 启动时检测 运行时可能出错 运行时可能出错
单元测试难度 低(可手动创建) 中(需调用 Setter) 高(需反射或 Mock)
依赖可见性 明确(构造器参数) 较明确(Setter 方法) 隐藏(字段注解)
适用场景 核心组件、不可变依赖 可选依赖、动态配置 简单组件、快速开发

最佳实践

  1. 优先使用构造器注入:

    • 确保依赖不可变且强制注入。
    • 符合单一职责原则和依赖倒置原则。
  2. 使用 Setter 注入处理可选依赖:

    • 例如配置参数、可替换的组件。
  3. 谨慎使用字段注入:

    • 仅在无法使用构造器或 Setter 时(如框架限制)使用。
    • 避免在需要测试的组件中使用。
  4. 避免接口注入:

    • 耦合度高,不符合现代开发实践。

总结

构造器注入和 Setter 注入是最常用的方式,选择时需根据依赖的性质(强制 / 可选、可变 / 不可变)和组件的设计目标来决定。字段注入虽然简洁,但存在测试困难和依赖隐藏的问题,应谨慎使用。

相关推荐
Moshow郑锴30 分钟前
sql-pipeline - 基于PostgreSQL的SQL健康检查与发布编排平台
java·sql
谢亮_vipxieliang8 小时前
Spring Cloud 服务治理入门:注册发现、配置中心、网关限流、熔断降级与分布式一致性方案
分布式·spring·spring cloud
Wang's Blog8 小时前
Java 项目实战: 外卖平台优化-Nginx配置文件结构与块层级
java·开发语言·nginx
\光辉岁月/9 小时前
5.java-数组
java·开发语言
谢亮_vipxieliang9 小时前
Spring 事务失效的常见场景
java·开发语言·数据库·spring boot
郑州光合科技余经理10 小时前
海外版外卖加盟:总站与分站配送规则怎么分开管
java·开发语言·前端·后端·uni-app·php·ai编程
2601_9620715710 小时前
类变量和全局变量的生命周期有什么区别?
java·开发语言·jvm
code2cat10 小时前
Java进阶篇之AtomicReference:一次替换引用,读到一份完整状态
java·并发编程·不可变对象·atomicreference
专业程序开发源10 小时前
springboot简历管理系统81389-计算机课程设计、毕业设计
java·vue.js·spring boot·后端·spring·php·课程设计
Wang's Blog10 小时前
Java 项目实战: 外卖平台优化-前后端分离开发模式与工程拆分
java·开发语言