注入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 简化

相关推荐
cat三三3 小时前
java之异常
java·开发语言
浙江第二深情3 小时前
前端性能优化终极指南
java·maven
养乐多07223 小时前
【Java】IO流
java
俊男无期3 小时前
超效率工作法
java·前端·数据库
中国胖子风清扬3 小时前
SpringAI和 Langchain4j等 AI 框架之间的差异和开发经验
java·数据库·人工智能·spring boot·spring cloud·ai·langchain
月明长歌4 小时前
【码道初阶】牛客TSINGK110:二叉树遍历(较难)如何根据“扩展先序遍历”构建二叉树?
java·数据结构·算法
用户2190326527354 小时前
Spring Boot + Redis 注解极简教程:5分钟搞定CRUD操作
java·后端
Alice4 小时前
linux scripts
java·linux·服务器
Filotimo_4 小时前
Spring Data JPA 方法名查询特性的使用
java·开发语言·windows
代码栈上的思考4 小时前
MyBatis:注解方式实现数据库 CRUD 全操作
java·开发语言·mybatis