Spring如何将配置文件中的简单值注入Bean中

 更新时间:2025年07月11日 08:31:43   作者:冰糖心书房  
Spring 提供了几种优雅的方式来将配置文件中的简单值(如字符串、数字、布尔值等)注入到 Bean 中,下面小编就为大家介绍一下两种主流的方法吧

Spring 提供了几种优雅的方式来将配置文件中的简单值(如字符串、数字、布尔值等)注入到 Bean 中。

主要有两种主流方法:

  • 使用 @Value 注解:简单直接,适合注入单个值。
  • 使用 @ConfigurationProperties:类型安全,适合将一组相关的配置属性映射到一个对象上,是 Spring Boot 官方推荐的方式。

方法一:使用@Value注解(简单直接)

@Value 是最直接的方式,它可以从属性文件、环境变量、系统属性等地方读取值并注入到字段中。

步骤 1:在application.properties中定义属性

# 字符串
app.name=My Awesome Application
# 数字
app.thread-pool.size=10
# 布尔值
app.feature.new-ui.enabled=true
# 逗号分隔的列表
app.admin.emails=admin@example.com,support@example.com
# 带默认值的属性 (我们在代码中处理)
# app.description=... (假设这个属性没有被定义)

步骤 2:在 Bean 中使用@Value注入

@Value 使用 ${...} 占位符语法来引用属性。

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import jakarta.annotation.PostConstruct; // 使用 jakarta.* 如果是 Spring Boot 3+
import java.util.List;

@Component
public class AppConfig {

    // 注入字符串
    @Value("${app.name}")
    private String appName;

    // Spring 会自动进行类型转换,将 "10" 转换为 int
    @Value("${app.thread-pool.size}")
    private int threadPoolSize;

    // 同样,"true" 会被转换为 boolean
    @Value("${app.feature.new-ui.enabled}")
    private boolean isNewUiEnabled;

    // 注入一个列表 (Spring 会自动按逗号分割)
    @Value("${app.admin.emails}")
    private List<String> adminEmails;

    // 提供默认值:如果属性不存在,则使用冒号后面的默认值
    @Value("${app.description:This is a default description}")
    private String appDescription;
    
    // 打印出来看看结果
    @PostConstruct
    public void printConfig() {
        System.out.println("Application Name: " + appName);
        System.out.println("Thread Pool Size: " + threadPoolSize);
        System.out.println("Is New UI Enabled: " + isNewUiEnabled);
        System.out.println("Admin Emails: " + adminEmails);
        System.out.println("Application Description: " + appDescription);
    }
}

@Value 的优点:

  • 非常简单,用于注入少量、零散的配置时非常方便。
  • 支持 SpEL(Spring Expression Language),功能强大,例如可以注入其他 Bean 的属性值:@Value("#{otherBean.someProperty}")

@Value 的缺点:

  • 当属性很多时,代码会变得冗长和分散。
  • 不是类型安全的。如果你在属性文件中写了一个非数字的值给 threadPoolSize,错误只会在运行时才会暴露。
  • 重构不友好(比如修改属性前缀)。

方法二:使用@ConfigurationProperties(官方推荐)

这种方式将一组相关的配置属性绑定到一个类型安全的 POJO(Plain Old Java Object)上。

步骤 1:在application.properties中定义属性(与上面相同)

app.name=My Awesome Application
app.thread-pool.size=10
app.feature.new-ui.enabled=true
app.admin.emails=admin@example.com,support@example.com

步骤 2:创建一个配置属性类

这个类就是一个普通的 Java 类,包含了与配置文件中属性名对应的字段。

import org.springframework.boot.context.properties.ConfigurationProperties;
import java.util.List;

// 这个注解告诉 Spring,将 "app" 前缀的属性绑定到这个类的字段上
@ConfigurationProperties(prefix = "app")
public class AppProperties {

    private String name;
    private List<String> adminEmails;
    // 注意:这里我们创建一个嵌套类来映射嵌套的属性,结构更清晰
    private final ThreadPool threadPool = new ThreadPool();
    private final Feature feature = new Feature();

    // 嵌套类,用于映射 app.thread-pool.*
    public static class ThreadPool {
        private int size;
        // Getter and Setter...
        public int getSize() { return size; }
        public void setSize(int size) { this.size = size; }
    }

    // 嵌套类,用于映射 app.feature.*
    public static class Feature {
        private final NewUi newUi = new NewUi();
        public static class NewUi {
            private boolean enabled;
            // Getter and Setter...
            public boolean isEnabled() { return enabled; }
            public void setEnabled(boolean enabled) { this.enabled = enabled; }
        }
        public NewUi getNewUi() { return newUi; }
    }

    // 主类的 Getters and Setters...
    public String getName() { return name; }
    public void setName(String name) { this.name = name; }
    public List<String> getAdminEmails() { return adminEmails; }
    public void setAdminEmails(List<String> adminEmails) { this.adminEmails = adminEmails; }
    public ThreadPool getThreadPool() { return threadPool; }
    public Feature getFeature() { return feature; }
}

注意

  • Spring Boot 会自动将 kebab-case(如 thread-pool.size)或 snake_case(thread_pool.size)的属性名映射到 camelCase(threadPool.size)的字段名。
  • 必须提供标准的 Getters 和 Setters,Spring Boot 通过它们来设置值。

步骤 3:在主配置类中启用这个属性类

import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
// 告诉 Spring Boot 启用 AppProperties,并将其注册为一个 Bean
@EnableConfigurationProperties(AppProperties.class)
public class MyApplication {
    public static void main(String[] args) {
        SpringApplication.run(MyApplication.class, args);
    }
}

步骤 4:在任何其他 Bean 中注入和使用这个属性对象

现在,你可以像注入任何其他 Service 一样,注入整个 AppProperties 对象。

import org.springframework.stereotype.Service;

@Service
public class MyBusinessService {

    private final AppProperties appProperties;

    // 通过构造函数注入,非常清晰
    public MyBusinessService(AppProperties appProperties) {
        this.appProperties = appProperties;
    }

    public void doSomething() {
        System.out.println("Running service for app: " + appProperties.getName());
        if (appProperties.getFeature().getNewUi().isEnabled()) {
            System.out.println("Using the new UI with thread pool size: " + appProperties.getThreadPool().getSize());
        }
    }
}

总结:@Valuevs@ConfigurationProperties

特性@Value@ConfigurationProperties (推荐)
用途注入单个、零散的值将一组相关的配置绑定到一个对象
类型安全运行时检查,弱类型编译时绑定(部分 IDE 支持),强类型
代码组织配置分散在多个类中配置集中在一个 POJO 中,结构清晰
验证不支持 JSR-303 验证支持 @Validated 注解进行数据校验
IDE 支持弱(简单的字符串跳转)强大(在 .properties 文件中输入时会有代码提示和元数据支持)
灵活性支持 SpEL,更灵活面向结构化配置,更规范

最佳实践:

  • 优先使用 @ConfigurationProperties。它让你的代码更健壮、更易于维护和测试。
  • 只有当你需要注入单个与其他配置无关的值,或者需要利用 SpEL 的强大功能时,考虑使用 @Value。

到此这篇关于Spring如何将配置文件中的简单值注入Bean中的文章就介绍到这了,更多相关Spring注入Bean内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Java模拟并解决缓存穿透问题

    Java模拟并解决缓存穿透问题

    这篇文章主要介绍了Java模拟并解决缓存穿透问题,本文给大家介绍的非常详细,具有一定的参考借鉴价值 ,需要的朋友可以参考下
    2019-08-08
  • springboot连接Redis的教程详解

    springboot连接Redis的教程详解

    这篇文章主要介绍了springboot连接Redis的教程详解,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-03-03
  • Java探索之string字符串的应用代码示例

    Java探索之string字符串的应用代码示例

    这篇文章主要介绍了Java探索之string字符串的应用代码示例,具有一定参考价值,需要的朋友可以了解下。
    2017-10-10
  • spring之Bean的生命周期详解

    spring之Bean的生命周期详解

    本篇文章主要介绍了spring之Bean的生命周期详解,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-05-05
  • IntelliJ idea 如何生成动态的JSON字符串(步骤详解)

    IntelliJ idea 如何生成动态的JSON字符串(步骤详解)

    这篇文章主要介绍了IntelliJ idea 如何生成动态的JSON字符串,本文分步骤给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-08-08
  • java如何实现图片转化为数据流

    java如何实现图片转化为数据流

    这篇文章主要介绍了java如何实现图片转化为数据流,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-01-01
  • 关于线程池异步线程中再次获取线程池资源的问题

    关于线程池异步线程中再次获取线程池资源的问题

    这篇文章主要介绍了关于线程池异步线程中再次获取线程池资源的问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-08-08
  • Java 配置加载机制详解及实例

    Java 配置加载机制详解及实例

    这篇文章主要介绍了Java 配置加载机制详解及实例的相关资料,需要的朋友可以参考下
    2016-09-09
  • java中Hutool包的常用方法总结

    java中Hutool包的常用方法总结

    这篇文章主要为大家详细介绍了java在工作中中Hutool包的一些常用方法总结,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下
    2023-12-12
  • SpringBoot中的@Inherited注解详解

    SpringBoot中的@Inherited注解详解

    这篇文章主要介绍了SpringBoot中的@Inherited注解详解,@Inherited是一个标识,用来修饰注解,如果一个类用上了@Inherited修饰的注解,那么其子类也会继承这个注解,需要的朋友可以参考下
    2023-08-08

最新评论