注入Java Bean的方式

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


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

  • 说明:按类型自动装配,可作用于构造器、Setter 方法、字段或普通方法。

  • 场景:大多数情况下的依赖注入。

  • 示例

    java 复制代码
    @Service
    public class MyService {
        @Autowired // 字段注入
        private MyRepository repository;
    }

2. 构造器注入(推荐)

  • 说明 :通过构造器注入依赖,Spring 4.3+ 中若类只有单个构造器,可省略 @Autowired

  • 优势:强制依赖不可变,避免空指针。

  • 示例

    java 复制代码
    @Service
    public class MyService {
        private final MyRepository repository;
    
        public MyService(MyRepository repository) { // 自动注入
            this.repository = repository;
        }
    }

3. @Resource 注解

  • 说明:按名称注入(JSR-250 规范),默认按字段名或方法名匹配 Bean。

  • 场景:需明确指定 Bean 名称时。

  • 示例

    java 复制代码
    @Service
    public class MyService {
        @Resource(name = "myRepositoryImpl")
        private MyRepository repository;
    }

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

  • 说明 :在 @Configuration 类中定义 @Bean 方法,返回对象由 Spring 管理。

  • 场景:配置第三方库组件或复杂 Bean。

  • 示例

    java 复制代码
    @Configuration
    public class AppConfig {
        @Bean
        public DataSource dataSource() {
            return new HikariDataSource();
        }
    }

5. @Value 注解

  • 说明:注入配置文件属性或 SpEL 表达式。

  • 场景:注入简单值(如字符串、数字)或动态表达式。

  • 示例

    java 复制代码
    @Component
    public class MyComponent {
        @Value("${app.timeout:1000}") // 注入配置,默认值 1000
        private int timeout;
    }

6. XML 配置(传统方式)

  • 说明 :通过 XML 定义 Bean,需配合 @ImportResource 导入。

  • 场景:遗留项目迁移或混合配置。

  • 示例

    xml 复制代码
    <!-- applicationContext.xml -->
    <bean id="myBean" class="com.example.MyBean"/>
    java 复制代码
    @SpringBootApplication
    @ImportResource("classpath:applicationContext.xml")
    public class App { ... }

7. ApplicationContextAware 手动获取

  • 说明 :实现接口获取 ApplicationContext,直接调用 getBean()

  • 场景:非 Spring 管理类中动态获取 Bean(不推荐常规使用)。

  • 示例

    java 复制代码
    @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 复制代码
    @Service
    public class MyService {
        @Inject
        private MyRepository repository;
    }

9. Setter 方法注入

  • 说明 :通过 @Autowired 注解标记在 Setter 方法上,Spring 会调用该方法注入依赖。

  • 场景

    • 可选依赖:依赖不是必须的(例如有默认实现)。
    • 动态重新注入:需要运行时更换依赖(较少见)。
  • 示例

    java 复制代码
    @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 注入允许依赖在对象创建后修改(除非代码刻意限制),可能破坏不变性。
  2. 代码简洁性

    • 构造器注入无需写 Setter 方法,减少样板代码(尤其配合 Lombok @RequiredArgsConstructor)。
  3. 框架演进

    • Spring 官方自 4.x 起推荐构造器注入,明确依赖的强制性,提升组件可靠性。

Setter 注入的合理使用场景

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

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


9. 构造器注入最新方式

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

java 复制代码
@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 简化代码)。
分类 目的 典型技术
声明 Bean 告诉 Spring 管理哪些对象 @Component, @Bean, XML
依赖注入 解决 Bean 之间的依赖关系 构造器注入、Setter、@Autowired、Lombok 简化

相关推荐
椎4957 分钟前
苍穹外卖资源点整理+个人错误解析-Day10-订单状态定时处理(Spring Task)、来单提醒和客户催单
java·后端·spring
Y***h18713 分钟前
eclipse配置Spring
java·spring·eclipse
東雪木13 分钟前
变量与数据类型
java·开发语言
p***629916 分钟前
CVE-2024-38819:Spring 框架路径遍历 PoC 漏洞复现
java·后端·spring
Lisonseekpan16 分钟前
Java分词器深度评测与实战指南
java·开发语言·后端
饕餮争锋37 分钟前
Kotlin: [Internal Error] java.lang.NoSuchFieldError: FILE_HASHING_STRATEGY
java·kotlin
明洞日记40 分钟前
【设计模式手册014】解释器模式 - 语言解释的优雅实现
java·设计模式·解释器模式
lichong9511 小时前
XLog debug 开启打印日志,release 关闭打印日志
android·java·前端
xu_yule1 小时前
Linux_14(多线程)线程控制+C++多线程
java·开发语言·jvm
合作小小程序员小小店1 小时前
网页开发,在线%新版本旅游管理%系统,基于eclipse,html,css,jquery,servlet,jsp,mysql数据库
java·数据库·eclipse·html·intellij-idea·旅游·jsp