注入Java Bean的方式

简介: 本文总结了 Spring Boot 中常见的 Bean 注入方式,包括字段注入(`@Autowired`)、构造器注入(推荐)、Setter 方法注入、`@Resource` 按名称注入、`@Bean` 定义复杂 Bean、`@Value` 注入配置值、XML 配置、`ApplicationContextAware` 手动获取 Bean 以及 JSR-330 的 `@Inject`。同时分析了 Setter 注入逐渐被淡化的原因,强调构造器注入的不可变性和安全性优势,并推荐结合 Lombok 简化代码。文章还提供了按需选择注解的建议和最佳实践,帮助开发者根据场景选择合适的依赖注入方式。

Spring Boot 中注入 Bean 的常见方式如下,每种方式适用于不同的场景:


1. @Autowired 注解(字段注入)

  • 说明:按类型自动装配,可作用于构造器、Setter 方法、字段或普通方法。
  • 场景:大多数情况下的依赖注入。
  • 示例

java

  • 体验AI代码助手
  • 代码解读
  • 复制代码
@Service
public class MyService {
    @Autowired // 字段注入
    private MyRepository repository;
}

2. 构造器注入(推荐)

  • 说明:通过构造器注入依赖,Spring 4.3+ 中若类只有单个构造器,可省略 @Autowired
  • 优势:强制依赖不可变,避免空指针。
  • 示例

java

  • 体验AI代码助手
  • 代码解读
  • 复制代码
@Service
public class MyService {
    private final MyRepository repository;

    public MyService(MyRepository repository) { // 自动注入
        this.repository = repository;
    }
}

3. @Resource 注解

  • 说明:按名称注入(JSR-250 规范),默认按字段名或方法名匹配 Bean。
  • 场景:需明确指定 Bean 名称时。
  • 示例

java

  • 体验AI代码助手
  • 代码解读
  • 复制代码
@Service
public class MyService {
    @Resource(name = "myRepositoryImpl")
    private MyRepository repository;
}

4. @Bean 方法(Java 配置类)

  • 说明:在 @Configuration 类中定义 @Bean 方法,返回对象由 Spring 管理。
  • 场景:配置第三方库组件或复杂 Bean。
  • 示例

java

  • 体验AI代码助手
  • 代码解读
  • 复制代码
@Configuration
public class AppConfig {
    @Bean
    public DataSource dataSource() {
        return new HikariDataSource();
    }
}

5. @Value 注解

  • 说明:注入配置文件属性或 SpEL 表达式。
  • 场景:注入简单值(如字符串、数字)或动态表达式。
  • 示例

java

  • 体验AI代码助手
  • 代码解读
  • 复制代码
@Component
public class MyComponent {
    @Value("${app.timeout:1000}") // 注入配置,默认值 1000
    private int timeout;
}

6. XML 配置(传统方式)

  • 说明:通过 XML 定义 Bean,需配合 @ImportResource 导入。
  • 场景:遗留项目迁移或混合配置。
  • 示例

xml

  • 体验AI代码助手
  • 代码解读
  • 复制代码
<!-- applicationContext.xml -->
<bean id="myBean" class="com.example.MyBean"/>

java

  • 体验AI代码助手
  • 代码解读
  • 复制代码
@SpringBootApplication
@ImportResource("classpath:applicationContext.xml")
public class App { ... }

7. ApplicationContextAware 手动获取

  • 说明:实现接口获取 ApplicationContext,直接调用 getBean()
  • 场景:非 Spring 管理类中动态获取 Bean(不推荐常规使用)。
  • 示例

java

  • 体验AI代码助手
  • 代码解读
  • 复制代码
@Component
public class MyBean implements ApplicationContextAware {
    private ApplicationContext context;

    @Override
    public void setApplicationContext(ApplicationContext context) {
        this.context = context;
    }

    public void useBean() {
        MyService service = context.getBean(MyService.class);
    }
}

8. JSR-330 的 @Inject 注解

  • 说明:与 @Autowired 功能类似,需引入 javax.inject 依赖。
  • 示例

java

  • 体验AI代码助手
  • 代码解读
  • 复制代码
@Service
public class MyService {
    @Inject
    private MyRepository repository;
}

9. Setter 方法注入

  • 说明:通过 @Autowired 注解标记在 Setter 方法上,Spring 会调用该方法注入依赖。
  • 场景
  • 可选依赖:依赖不是必须的(例如有默认实现)。
  • 动态重新注入:需要运行时更换依赖(较少见)。
  • 示例

java

  • 体验AI代码助手
  • 代码解读
  • 复制代码
@Service
public class MyService {
    private MyRepository repository;

    @Autowired // Setter 方法注入
    public void setRepository(MyRepository repository) {
        this.repository = repository;
    }
}

Setter 方法注入是 Spring 中另一种常见的依赖注入方式,尤其是在早期 Spring 版本中广泛使用。可能因为它在现代 Spring Boot 项目中逐渐被构造器注入取代(官方推荐)


为什么 Setter 注入逐渐被淡化?

  1. 不可变性与安全性
  • 构造器注入能确保依赖在对象创建时就被初始化,避免 NullPointerException
  • Setter 注入允许依赖在对象创建后修改(除非代码刻意限制),可能破坏不变性。
  1. 代码简洁性
  • 构造器注入无需写 Setter 方法,减少样板代码(尤其配合 Lombok @RequiredArgsConstructor)。
  1. 框架演进
  • Spring 官方自 4.x 起推荐构造器注入,明确依赖的强制性,提升组件可靠性。

Setter 注入的合理使用场景

  • 可选依赖:依赖可能为 null,且有默认处理逻辑。

java

  • 体验AI代码助手
  • 代码解读
  • 复制代码
@Autowired(required = false) // 依赖不存在时不报错
public void setOptionalDependency(OptionalDependency dep) {
    this.dep = dep != null ? dep : new DefaultDependency();
}
  • 循环依赖:某些复杂场景下,Setter 注入可配合 @Lazy 解决循环依赖(但设计上应尽量避免循环依赖)。

9. 构造器注入最新方式

通过类的构造器注入依赖,结合 Lombok 的 @RequiredArgsConstructor 可自动生成构造器。

java

体验AI代码助手

代码解读

复制代码

@Service
@RequiredArgsConstructor // Lombok 自动生成构造器(注入方式)
public class UserService {
    private final UserRepository userRepository; // 依赖
}

为什么 Lombok 属于依赖注入?

  • Lombok 的作用:通过 @RequiredArgsConstructor 自动生成包含 final 字段的构造器,减少了手动编写构造器的代码量。
  • Spring 的配合:当类被声明为 Bean(如 @Service)后,Spring 会自动通过生成的构造器完成依赖注入。
  • 本质:Lombok 只是简化了依赖注入的代码编写,不参与 Bean 的声明过程

  • 优先使用构造器注入:强制依赖、不可变性、代码简洁性。
  • 按需使用 Setter 注入:可选依赖或特殊场景。
  • 避免滥用字段注入:虽然方便,但隐藏依赖关系,不利于测试和维护。

总结

  • 推荐方式:构造器注入(不可变依赖) + @Autowired(可选依赖)。
  • 避免使用:字段注入(不利于测试)和 ApplicationContextAware(破坏控制反转)。
  • 按需选择@Resource(按名称注入)、@Value(配置值)或 @Bean(复杂配置)。
  • Lombok 属于依赖注入的优化工具
  • 最佳实践:使用 @Component 等注解声明 Bean + 构造器注入(配合 Lombok 简化代码)。


转载来源:https://juejin.cn/post/7493866403407134746

相关文章
|
XML Java 开发者
Spring Boot中的bean注入方式和原理
Spring Boot中的bean注入方式和原理
2099 0
|
XML Java 数据库
探索 Spring Boot 中的 @Configuration 注解:核心概念与应用
【4月更文挑战第20天】在 Spring Boot 项目中,@Configuration 注解扮演了一个关键角色,它标识一个类作为配置源,这些配置用于定义和管理 Spring 应用程序中的 Bean
3039 7
|
SQL Java 数据库连接
MyBatis动态SQL字符串空值判断,这个细节99%的程序员都踩过坑!
本文深入探讨了MyBatis动态SQL中字符串参数判空的常见问题。通过具体案例分析,对比了`name != null and name != &#39;&#39;`与`name != null and name != &#39; &#39;`两种写法的差异,指出后者可能引发逻辑混乱。为避免此类问题,建议在后端对参数进行预处理(如trim去空格),简化MyBatis判断逻辑,提升代码健壮性与可维护性。细节决定成败,严谨处理参数判空是写出高质量代码的关键。
1970 0
|
Java 测试技术 程序员
为什么Spring不推荐@Autowired用于字段注入?
作为Java程序员,Spring框架在日常开发中使用频繁,其依赖注入机制带来了极大的便利。然而,尽管@Autowired注解简化了依赖注入,Spring官方却不推荐在字段上使用它。本文将探讨字段注入的现状及其存在的问题,如难以进行单元测试、违反单一职责原则及易引发NPE等,并介绍为何Spring推荐构造器注入,包括增强代码可读性和维护性、方便单元测试以及避免NPE等问题。通过示例代码展示如何将字段注入重构为构造器注入,提高代码质量。
706 1
|
XML Java 测试技术
Spring Boot中的依赖注入和控制反转
Spring Boot中的依赖注入和控制反转
|
缓存 NoSQL 算法
高并发秒杀系统实战(Redis+Lua分布式锁防超卖与库存扣减优化)
秒杀系统面临瞬时高并发、资源竞争和数据一致性挑战。传统方案如数据库锁或应用层锁存在性能瓶颈或分布式问题,而基于Redis的分布式锁与Lua脚本原子操作成为高效解决方案。通过Redis的`SETNX`实现分布式锁,结合Lua脚本完成库存扣减,确保操作原子性并大幅提升性能(QPS从120提升至8,200)。此外,分段库存策略、多级限流及服务降级机制进一步优化系统稳定性。最佳实践包括分层防控、黄金扣减法则与容灾设计,强调根据业务特性灵活组合技术手段以应对高并发场景。
3638 7
|
SQL JSON 前端开发
较为完整的SpringBoot项目结构
本文介绍了SpringBoot项目的分层结构与目录组成。项目分为四层:**controller层**(前端交互)、**service层**(业务逻辑处理)、**dao层**(数据库操作)和**model层**(实体类定义)。分层设计旨在实现关注点分离,降低耦合度,提高系统灵活性、可维护性和扩展性。此外,还详细说明了项目目录结构,包括`controller`、`service`、`dao`、`entity`、`param`、`util`等子目录的功能划分,便于团队协作开发。此架构有助于前后端分离,明确各模块职责,符合高内聚低耦合的设计原则。
7479 1
|
缓存 安全 Java
Spring Boot 3 集成 Spring Security + JWT
本文详细介绍了如何使用Spring Boot 3和Spring Security集成JWT,实现前后端分离的安全认证概述了从入门到引入数据库,再到使用JWT的完整流程。列举了项目中用到的关键依赖,如MyBatis-Plus、Hutool等。简要提及了系统配置表、部门表、字典表等表结构。使用Hutool-jwt工具类进行JWT校验。配置忽略路径、禁用CSRF、添加JWT校验过滤器等。实现登录接口,返回token等信息。
7890 14
Spring Boot 3 集成 Spring Security + JWT
@RequiredArgsConstructor(onConstructor=@_(@Autowired))是什么语法?
@RequiredArgsConstructor(onConstructor=@_(@Autowired))是什么语法?
687 0
|
前端开发 Java 数据格式
SpringBoot中定义Bean的几种方式
本文介绍了Spring Boot中定义Bean的多种方式,包括使用@Component、@Bean、@Configuration、@Import等注解及Java配置类。每种方式适用于不同的场景,帮助开发者高效管理和组织应用组件。
767 0