SpringBoot整体读取多个配置属性及其相关操作方法

 更新时间:2025年07月14日 08:54:47   作者:NE_STOP  
本文介绍SpringBoot中@ConfigurationProperties用于批量读取配置属性,对比@Value,涵盖其用法、配置选项、List处理及校验功能,支持宽松绑定与属性转换,需相关依赖启用,感兴趣的朋友一起看看吧

上篇文章讲到使用@Value注解每次只能读取一个配置属性,若要整体读取多个属性,或者读取具有某种结构关系的一组属性可使用@ConfigurationProperties注解来处理。

@ConfigurationProperties注解的两种用法:

  • 修饰属性处理类:当@ConfigurationProperties修饰的类被部署为容器中的Bean时,改注解指定的属性会被注入该Bean的属性。因此,@ConfigurationProperties修饰的类称为“属性处理类”。
  • 修饰@Bean注解修饰的方法:使用@Bean修饰的方法蒋会配置一个容器中的Bean,而@ConfigurationProperties指定的属性会被注入该Bean的属性。

看不懂没关系,下面会有代码示例。

在使用@ConfigurationProperties时可指定如下属性:

  • prefix(或value):指定要加载的属性的前缀
  • ignoreInvaildFields():指定是否忽略无效属性值。比如处理类定义了某个字段的类型是Integer,但在配置文件中的值是abc,这就是无效值。
  • ignoreUnknowFields():指定是否忽略未知的字段值。如果在配置文件中配置的属性比处理类需要的属性更多,那么多出来的属性就是未知属性。

使用属性处理类获取配置属性

直接来看代码示例:

\resources\application.properties文件内容:

org.crazyit.enabled=true
org.crazyit.name=Crazy Java
org.crazyit.remoteAddress=192.168.1.188
org.crazyit.item.brand=Tesla
org.crazyit.item.comments=Good, Excellent

(使用IDEA开发属性处理类时,添加spring-boot-configuration-processor依赖,IDEA会提供“代码补全”功能。

<!-- 添加该依赖后IDEA可以提供自动补全功能 -->
<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-configuration-processor</artifactId>
   <optional>true</optional>
</dependency>

)

SpringBoot不会自动启用@ConfigurationProperties注解,启用该注解有如下方式:

  • 为@ConfigurationProperties注解修饰的类加@Component注解
  • 为@ConfigurationProperties注解修饰的类显式配置成容器中的bean
  • 使用@EnableConfigurationProperties注解,该注解显式指定一个或多个属性处理类,SpringBoot会启用这些属性处理类上的@ConfigurationProperties注解
  • 使用@ConfigurationPropertiesScan注解,该注解指定一个或多个包及其子包下所有带@ConfigurationProperties注解的类

@ConfigurationProperties注解修饰的属性处理类代码:

// 指定读取以org.crazyit.*开头的属性
@ConfigurationProperties(prefix = "org.crazyit", ignoreUnknownFields=false)
@Component
public class CrazyitProperties
{
    // 指定同名的实例变量和setter方法。SpringBoot会通过反射调用setter方法来完成属性值注入
   private boolean enabled;
   private String name;
   private InetAddress remoteAddress;
   private final Item item = new Item();
         // 省略getter\setter 
   public static class Item
   {
      private String brand;
      private List<String> comments = new ArrayList<>(Collections.singleton("GREAT"));
            // 省略getter\setter 
   }
}

控制器类代码示例:

@RestController
public class HelloController
{
   private final CrazyitProperties crazyitProperties;
   // 依赖注入CrazyitProperties属性处理Bean
   @Autowired
   public HelloController(CrazyitProperties crazyitProperties)
   {
      this.crazyitProperties = crazyitProperties;
   }
   @GetMapping
   public CrazyitProperties hello()
   {
      return crazyitProperties;
   }
}

运行结果:

属性处理类也支持使用构造器完成属性值注入,但是要额外使用@ConstructorBinding修饰用于执行构造注入的构造器。注意:使用构造器注入,必须使用@EnableConfigurationProperties或者@ConfigurationPropertiesScan注解来启用@ConfigurationProperties注解。

属性处理类示例:

@ConfigurationProperties(prefix = "org.crazyit", ignoreUnknownFields=false)
public class CrazyitProperties
{
   private boolean enabled;
   private String name;
   private InetAddress remoteAddress;
   private final Item item;
   @ConstructorBinding
   public CrazyitProperties(boolean enabled, String name, InetAddress remoteAddress, Item item)
   {
      this.enabled = enabled;
      this.name = name;
      this.remoteAddress = remoteAddress;
      this.item = item;
   }
       // 省略getter\setter 
   public static class Item
   {
      private String brand;
      private List<String> comments = new ArrayList<>(Collections.singleton("GREAT"));
       // 省略getter\setter 
   }
}

application.yml

org:
  crazyit:
    enabled: true
    name: 哈利波特
    remote-address: 192.168.1.188
    item:
      brand: Apple
      comments:
        - Good
        - Excellent

上面配置的属性为org.crazyit.remote-address与CrazyitProperties类中定义的remoteAddress属性不完全相同,SpringBoot能成功注入吗?

答案是肯定的,因为SpringBoot支持宽松绑定(Relaxed Binding)。它不要求配置的属性名和属性处理类中的属性名完全相同。

宽松绑定的四种情况(这4种情况都能完成注入):

  • org.crazyit.remote-address
  • org.crazyit. remoteAddress
  • org.crazyit. remote_address
  • ORG_CRAZYIT_REMOTEADDRESS

在*.properties和 *.yml文件中配置List类型的属性有较小的区别:

  • 在*.properties文件中配置List有2种方式:英文逗号隔开多个值;用标准方括号
  • 在 *.yml文件中配置List有2种方式:英文逗号隔开多个值;用短横线开头(例子所示)

因此,*.properties和 *.yml文件中,都可以用英文逗号隔开多个值来构建List。

App.java示例

@SpringBootApplication
// 指定扫描org.crazyit.app.config包及其子包下的@ConfigurationProperties注解修饰的类
@ConfigurationPropertiesScan("org.crazyit.app.config")
public class App
{
   public static void main(String[] args)
   {
      // 创建Spring容器、运行Spring Boot应用
      SpringApplication.run(App.class, args);
   }
}

为容器中的bean注入配置属性

@ConfigurationProperties注解除了可修饰类,还可修饰@Bean注解修饰的方法。

代码示例:Book类

public class Book
{
   private String title;
   private double price;
   private String author;
   private List<String> keywords;
	// 省略getter、setter
}

代码示例:配置类

@Configuration
public class MyConfig
{
   @Bean
   // @ConfigurationProperties注解会驱动Spring自动调用该Bean的setter方法
   @ConfigurationProperties("fkjava.book")
   public Book book()
   {
      return new Book();
   }
}

代码示例:application.yml

fkjava:
  book:
    title: "美语音标"
    price: 128
    author: "赖世雄"
    keywords:
      - 英语
      - 音标

代码示例:控制器类

@RestController
public class HelloController
{
   private final Book book;
    // 通过构造器注入Book对象
   @Autowired
   public HelloController(Book book)
   {
      this.book = book;
   }
   @GetMapping
   public Book hello()
   {
      return book;
   }
}

运行结果:

@Value和 @ConfigurationProperties的对比

特征@ConfigurationProperties@Value
注入的属性个数批量单个
宽松绑定支持部分支持
SpEL不支持支持
元数据支持支持不支持

属性转换

SpringBoot内置了常用的类型转换机制,如果在转换失败,则应用启动会失败,并抛出异常。如果要忽略转换失败的属性,可将@ConfigurationProperties注解的ignoreInvaildFields属性设为true(默认是false)。

SpringBoot可自动转换如下类型:Duration、Period、DataSize,并支持为属性值指定单位。

  • Duration类型可指定的单位:ns纳秒、μs微妙、ms毫秒、s秒、m分钟、h小时、d天。
  • Period类型可指定的单位:y年、m月、w星期、d天。(例如配置1y3d,代表1年3天)。
  • DataSize类型可指定的单位:B字节、KB千字节、MB兆字节、GB吉字节、TB太字节

代码示例:属性处理类

// 指定读取以org.crazyit.*开头的属性
@ConfigurationProperties(prefix = "org.crazyit")
@Component
public class CrazyitProperties
{
   private Duration timeout;
    //   @DurationUnit注解指定默认的时间单位
   @DurationUnit(ChronoUnit.SECONDS)
   private Duration lastTime;
   private Period runPeriod;
    // @DataSizeUnit注解指定默认的数据单位
   @DataSizeUnit(DataUnit.MEGABYTES)
   private DataSize maxSize;
	// 省略getter、setter
}

代码示例:application.properties

org.crazyit.timeout=30000
# 默认单位是秒
org.crazyit.last-time=45
org.crazyit.run-period=2m5d
org.crazyit.max-size=2

代码示例:控制器类

@RestController
public class HelloController
{
   private final CrazyitProperties crazyitProperties;
   // 依赖注入CrazyitProperties属性处理Bean
   @Autowired
   public HelloController(CrazyitProperties crazyitProperties)
   {
      this.crazyitProperties = crazyitProperties;
   }
   @GetMapping
   public Map<String, Object> hello()
   {
      System.out.println(crazyitProperties.getMaxSize().toKilobytes());
      return Map.of("props", crazyitProperties,
            "maxSize", crazyitProperties.getMaxSize().toKilobytes());
   }
}

运行结果:

校验@ConfigurationProperties

只要为属性处理类添加@Validated注解,并使用JSR303的校验注解修饰需要校验的示例变量,SpringBoot会自动校验配置文件中的属性值。如果某个属性校验不通过,应用会启动失败,并用FailureAnalyzer显式校验错误。

如果属性处理类包含复合类型的属性,且要对复合类型的子属性进行校验,则应为该复合类型的属性添加@Valid注解。

@ConfigurationProperties校验基于JSR303,因此必须添加JSR303依赖,spring-boot-starter-validation依赖库包含了JSR303的依赖,因此要在pom文件中添加以下依赖

<!-- 添加Spring Boot Validation依赖库 -->
<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-validation</artifactId>
</dependency>

属性处理类示例:

// 指定读取以org.crazyit.*开头的属性
@ConfigurationProperties(prefix = "org.crazyit", ignoreUnknownFields=false)
@Component
@Validated
public class CrazyitProperties
{
   @NotEmpty
   private String name;
   @Range(max = 150, min=90, message = "价格必须位于90~150之间")
   private double price;
   @Pattern(regexp = "[1][3-8][0-9]{9}", message = "必须输入有效的手机号")
   private String mobile;
   @Valid
   private final Item item = new Item();
	// 省略getter setter
   public static class Item
   {
      @Length(min=5, max=10, message = "品牌名长度必须在5到10个字符")
      private String brand;
      @Size(min = 1, message = "comments至少包含一个元素")
      private List<String> comments = new ArrayList<>(Collections.singleton("GREAT"));
	// 省略getter、setter
   }
}

代码示例:application.properties

org.crazyit.name=Crazy Java
org.crazyit.price=89
org.crazyit.mobile=13334444
org.crazyit.item.brand=Apple
org.crazyit.item.comments=Great, Excellent

运行结果:

对于使用@ConfigurationProperties修饰@Bean方法的情况,同样可对配置属性进行校验,主要为@Bean方法添加@Validated注解即可。

到此这篇关于SpringBoot整体读取多个配置属性及其相关操作的文章就介绍到这了,更多相关SpringBoot读取多个配置属性内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • java高效读大文件(csv,text)的几种处理方式

    java高效读大文件(csv,text)的几种处理方式

    这篇文章主要给大家介绍了关于java高效读大文件(csv,text)的几种处理方式,Java中处理大文件时,通常需要采取一些特定的策略来避免内存溢出或性能问题,文中通过代码及图片介绍的非常详细,需要的朋友可以参考下
    2024-07-07
  • java中HashMap的7种遍历方式与性能分析

    java中HashMap的7种遍历方式与性能分析

    本文主要介绍了java中HashMap的7种遍历方式与性能分析,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-11-11
  • 最新springboot中必须要了解的自动装配原理

    最新springboot中必须要了解的自动装配原理

    本文给大家介绍springboot中必须要了解的自动装配原理,spring-boot-dependencies:核心依赖都在父工程中,这个里面主要是管理项目的资源过滤及插件,本文对springboot自动装配原理给大家介绍的非常详细,需要的朋友参考下吧
    2022-05-05
  • Spring源码解析容器初始化构造方法

    Spring源码解析容器初始化构造方法

    这篇文章主要介绍了Spring源码解析容器初始化构造方法,文章围绕主题展开详细的内容介绍,具有一定的参考价值,需要的小伙伴可以参考一下
    2022-07-07
  • java中逻辑控制举例具体讲解

    java中逻辑控制举例具体讲解

    Java程序逻辑控制通俗说就是对代码执行顺序的控制,这篇文章主要给大家介绍了关于java中逻辑控制的相关资料,文中通过代码介绍的非常详细,需要的朋友可以参考下
    2024-01-01
  • java thread start()和run()方法简析

    java thread start()和run()方法简析

    本文以java中thread的start()和run()的区别做详细介绍, 需要了解跟多的朋友可以参考下
    2012-11-11
  • JDBC连接数据库的方法汇总

    JDBC连接数据库的方法汇总

    这篇文章主要介绍了JDBC连接数据库的方法,结合实例形式总结分析了JDBC连接各种常见数据库的相关实现技巧,需要的朋友可以参考下
    2016-08-08
  • MyBatis 延迟加载与缓存的实现

    MyBatis 延迟加载与缓存的实现

    本文主要介绍了MyBatis 延迟加载与缓存的实现
    2025-05-05
  • 值得收藏的2017年Java开发岗位面试题

    值得收藏的2017年Java开发岗位面试题

    这篇文章主要为大家推荐一份值得收藏的2017年Java开发岗位面试题,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-08-08
  • Spring Boot中@Autowired注入为空的原因以及解决方法

    Spring Boot中@Autowired注入为空的原因以及解决方法

    最近在开发中遇到了使用@Autowired注解自动装配时会报空指针,发现对象并没有装配进来,下面这篇文章主要给大家介绍了关于Spring Boot中@Autowired注入为空的原因以及解决方法,需要的朋友可以参考下
    2024-01-01

最新评论