Spring依赖注入方式

依赖注入方式

Spring框架主要支持以下三种依赖注入方式:构造器注入、Setter方法注入和字段注入。每种方式有各自的特点和适用场景。

构造器注入

通过类的构造器实现依赖注入,Spring容器在创建Bean实例时传入依赖对象。

特点

  • 强依赖性:适合必须依赖的场景,避免对象状态不完整。
  • 不可变性:注入后依赖不可变,适合final字段。
  • 线程安全:对象创建后依赖关系不再变化。

优点

  • 明确依赖关系,便于单元测试。
  • 避免循环依赖问题。
  • 符合不可变对象设计原则。

缺点

  • 参数较多时代码冗长。

示例

java 复制代码
@Service
public class UserService {
    private final UserRepository userRepository;

    @Autowired
    public UserService(UserRepository userRepository) {
        this.userRepository = userRepository;
    }
}
Setter方法注入

通过setter方法实现依赖注入,Spring容器调用setter方法传入依赖对象。

特点

  • 可选依赖:适合非必须依赖的场景。
  • 可重新注入:允许运行时重新配置依赖。

优点

  • 灵活性高,便于动态更换依赖。
  • 代码可读性好,参数多时更清晰。

缺点

  • 对象状态可能在生命周期中变化。
  • 可能隐藏依赖关系,导致NPE风险。

示例

java 复制代码
@Service
public class OrderService {
    private PaymentService paymentService;

    @Autowired
    public void setPaymentService(PaymentService paymentService) {
        this.paymentService = paymentService;
    }
}
字段注入

通过反射直接注入字段依赖,使用@Autowired注解标注字段。

特点

  • 简洁性:代码量最少,直接标注字段。
  • 隐蔽性:依赖关系不明显。

优点

  • 编写快速,适合快速原型开发。
  • 减少样板代码。

缺点

  • 难以进行单元测试(需要反射或Spring容器)。
  • 违反单一职责原则,容易过度注入。
  • 可能隐藏设计问题。

示例

java 复制代码
@Service
public class ProductService {
    @Autowired
    private InventoryService inventoryService;
}

选择建议

构造器注入适用场景

  • 强依赖的组件(如数据库访问层)
  • 需要不可变状态的场景
  • 希望明确显示所有依赖
  • Spring 4.3+版本中单构造器可省略@Autowired

Setter注入适用场景

  • 可选依赖配置
  • 需要动态重新配置的bean
  • 遗留代码改造场景

字段注入适用场景

  • 快速原型开发
  • 简单的控制器类
  • 内部工具类(非公共API)

最佳实践组合

  • 核心业务逻辑优先使用构造器注入
  • 可选基础设施组件使用setter注入
  • 控制器/简单bean可酌情使用字段注入
  • 避免混合使用多种注入方式

现代Spring推荐

Spring官方自4.x版本开始推荐构造器注入作为主要方式:

java 复制代码
@Service
public class ModernService {
    private final DependencyA a;
    private final DependencyB b;

    // Spring4.3+ 单构造器可自动装配
    public ModernService(DependencyA a, DependencyB b) {
        this.a = a;
        this.b = b;
    }
}

对于集合类型注入,Spring支持所有三种方式:

java 复制代码
// 构造器方式
public class CollectionInjection {
    private final List<Validator> validators;
    
    public CollectionInjection(List<Validator> validators) {
        this.validators = validators;
    }
}

// Setter方式
public void setValidators(List<Validator> validators) {
    this.validators = validators;
}

// 字段方式
@Autowired
private List<Validator> validators;

特殊注入场景

Optional依赖

Spring 5.0+支持Optional包装:

java 复制代码
public class OptionalService {
    private final Optional<SecondaryService> service;

    public OptionalService(Optional<SecondaryService> service) {
        this.service = service;
    }
}

懒加载注入

结合@Lazy注解实现延迟初始化:

java 复制代码
public class LazyService {
    @Lazy
    @Autowired
    private HeavyResource resource;
}

限定符注入

使用@Qualifier解决歧义:

java 复制代码
public class QualifierExample {
    @Autowired
    @Qualifier("mainDataSource")
    private DataSource dataSource;
}
相关推荐
kkkkk0211069 分钟前
微服务学习笔记(黑马商城)
java·spring boot·spring·spring cloud·sentinel·mybatis·java-rabbitmq
阿里云云原生12 分钟前
零代码改造 + 全链路追踪!Spring AI 最新可观测性详细解读
spring·云原生
数智顾问1 小时前
Flink ProcessFunction 与低层级 Join 实战手册:多流广告计费精确去重
java·spring boot·spring
Java水解1 小时前
【Spring】Spring事务和事务传播机制
后端·spring
白露与泡影2 小时前
BAT 大厂 java高频面试题汇总:JVM+Spring+ 分布式 +tomcat+MyBatis
java·jvm·spring
洛克大航海3 小时前
5-SpringCloud-服务链路追踪 Micrometer Tracing
后端·spring·spring cloud·zipkin·micrometer
我命由我123453 小时前
Spring Cloud - Spring Cloud 微服务概述 (微服务的产生与特点、微服务的优缺点、微服务设计原则、微服务架构的核心组件)
java·运维·spring·spring cloud·微服务·架构·java-ee
我命由我123454 小时前
Spring Cloud - Spring Cloud 注册中心与服务提供者(Spring Cloud Eureka 概述、微服务快速入门、微服务应用实例)
java·spring boot·spring·spring cloud·微服务·eureka·java-ee
MetaverseMan4 小时前
Java Spring 框架的`@Autowired` 注解 以及依赖注入分析
java·开发语言·spring
Java 码农5 小时前
Spring Cloud Eureka 的实现原理
spring·spring cloud·eureka