Spring配置参数详解


铿然架构 | 作者 / 铿然一叶 这是 铿然架构 的第 118 篇原创文章


1. 介绍

在应用系统中通常都需要通过获取配置参数来增加灵活性,例如数据库的用户名和密码、连接池配置,ssl配置等等。

配置参数有多种配置方式,如通过开源软件Nacos、Apollo配置,在K8S中通过Configmap或Secret配置,而Spring也提供了自身的参数配置和获取能力,本文将介绍Spring的配置参数能力和使用方式。

2. Spring配置参数

2.1 能力

● 参数来源:配置文件和环境变量。

● 文件格式:yml和properties文件。

● 参数类型:单值,数组,List,Map。

2.2 相关注解

Spring配置参数要使用注解,涉及注解如下:

注解 描述
PropertySource 用于指定配置参数来源文件,依赖Configuration注解才会生效。
Value 指定配置参数名或环境变量名,依赖Component注解才会生效。
ConfigurationProperties 指定配置参数获取时配置节点的起始位置,依赖Component注解才会生效。

注:因为Configuration注解包含了Component注解,因此Value和ConfigurationProperties注解依赖Configuration注解也一样有效。

2.3 配置例子

2.3.1 指定配置文件

如果不指定配置文件,默认从application.yml和application.properties中获取。

2.3.1.1 properties文件

java 复制代码
@Configuration
@PropertySource(value = "classpath:cluster.properties")
public class PropertiesConfiguration {
}

文件路径可以是classpath或绝对路径,绝对路径例子:

java 复制代码
"file:/home/app/cluster.properties"

2.3.1.2 yml文件

PropertySource注解默认不支持解析yaml文件,需要自定义一个工厂类来解析。

java 复制代码
@Configuration
@PropertySource(value = "classpath:cluster.yml", factory = YAMLPropertySourceFactory.class)
public class YAMLConfiguration {
}

工厂类代码:

java 复制代码
public class YAMLPropertySourceFactory implements PropertySourceFactory {
    public org.springframework.core.env.PropertySource<?> createPropertySource(String name, EncodedResource encodedResource) {
        YamlPropertiesFactoryBean factory = new YamlPropertiesFactoryBean();
        factory.setResources(encodedResource.getResource());

        Properties properties = factory.getObject();
        return name != null ? new PropertiesPropertySource(name, properties) :
                new PropertiesPropertySource(encodedResource.getResource().getFilename(),properties);
    }
}

2.3.2 指定配置节点起始位置

如下代码:

java 复制代码
@Component
@ConfigurationProperties(prefix = "db")
public class DBMapParam {

表示从db节点之后,即connectInfo开始读取配置参数:

java 复制代码
db:
  connectInfo:
    user: kengcoder
    password:  XDIxde!322332ec

如果配置为:

java 复制代码
@ConfigurationProperties(prefix = "db.connectInfo")

则从user开始读取。

2.3.3 Value注解配置方式

Value注解可以从文件或环境变量获取参数,支持单值,数组,List,Map。

代码:

java 复制代码
@Component
public class AppValueAndEnvParam {

    // 获取单值参数
    @Value("${app.name}")
    private String name;

    // 单值参数设置默认值,如果没有配置则取默认值
    @Value("${app.id:000}")
    private String defaultAppId;

    // 获取环境变量,如果配置和环境变量都有,优先取环境变量
    @Value("${JAVA_HOME}")
    private String javaHome;

    // 获取数组配置
    @Value("${app.whitelistIps}")
    private String[] whitelistIps;

    // 获取列表配置
    @Value("${app.whitelistIps}")
    private List<String> whitelistIpList;

    // 获取map配置
    @Value("#{${db.connectInfoForValue}}")
    private Map<String, String> dbConnectInfo;

    // 获取所有环境变量
    @Value("#{systemProperties}")
    private Map<String, String> systemPropertiesMap;
}

配置:

java 复制代码
app:
  name: myapp
  whitelistIps: 10.192.8.3,10.192.8.4,10.192.8.5
  
db:
  connectInfoForValue: '{"user": "kengcoder", "password": "XDIxde!322332ec", "url": "jdbc:mysql://10.9."}'

输出:

java 复制代码
(name=myapp, defaultAppId=000, javaHome=C:\Program Files\Java, whitelistIps=[10.192.8.3, 10.192.8.4, 10.192.8.5], whitelistIpList=[10.192.8.3, 10.192.8.4, 10.192.8.5], dbConnectInfo={user=kengcoder, password=XDIxde!322332ec, url=jdbc:mysql://10.9.})

2.3.4 Bean配置方式

Bean配置方式从配置文件获取参数,支持单值,数组,List,Map。

通过Bean方式配置,通常要指定配置参数起始节点。

2.3.4.1 复杂Bean

这里演示一个嵌套Bean配置,包括单值,数组和List参数。相关类如下:

代码:

java 复制代码
@Component
@ConfigurationProperties(prefix = "app")
public class ClusterObjectParam {
    private String name;
    private Cluster cluster;
}

@Data
@ToString
public class Cluster {
    private String id;
    private String name;
    private List<Node> nodes;
}

@Data
@ToString
public class Node {
    private String nodeId;
    private String nodeType;
    private Service[] services;
}

@Data
@ToString
public class Service {
    private String name;
    private int port;
}

配置:

java 复制代码
app:
  name: myapp
  cluster:
    id: c-101
    name: my-cluster
    nodes:
      - nodeId: n-101
        nodeType: app
        services:
          - name: account
            port: 8001
          - name: customer
            port: 8002
      - nodeId: n-102
        nodeType: db

输出:

java 复制代码
name: myapp
Cluster(id=c-101, name=my-cluster, nodes=[Node(nodeId=n-101, nodeType=app, services=[Service(name=account, port=8001), Service(name=customer, port=8002)]), Node(nodeId=n-102, nodeType=db, services=null)])

2.3.4.2 Map

代码:

java 复制代码
@Component
@ConfigurationProperties(prefix = "db")
public class DBMapParam {
    private Map<String, String> connectInfo;
}

配置:

java 复制代码
db:
  connectInfo: 
    user: kengcoder
    password:  XDIxde!322332ec
    url: "jdbc:mysql://10.9.2.7:3306/accountdb"

输出:

java 复制代码
{password=XDIxde!322332ec, url=jdbc:mysql://10.9.2.7:3306/accountdb, user=kengcoder}

2.3.5 两种配置方式比较

● 便利性

对于对象参数,Bean配置方式比较简单,只需要对象属性名和参数名一致,同时指定配置起点则可。

Value注解则需要一个个的指定配置参数名。

● 能力

两者都支持单值、数组、List、Map参数,Value支持从文件和环境变量获取参数,而Been配置方式只支持从文件获取参数。

● Map配置格式差异

两者Map参数的配置格式不同,配置不对会解析错误。

Value注解配置方式,必须是json格式的键值对:

java 复制代码
db:
  connectInfoForValue: '{"user": "kengcoder", "password": "XDIxde!322332ec", "url": "jdbc:mysql://10.9."}'

对象获取参数配置方式,直接配置键值对,不能是json格式:

java 复制代码
db:
  connectInfo: 
    user: kengcoder
    password:  XDIxde!322332ec
    url: "jdbc:mysql://10.9.2.7:3306/accountdb"

3. 总结

本文介绍了Spring的配置参数能力,其参数来源支持从配置文件和环境变量获取,文件格式支持properties和yaml,参数格式支持单值,数组,List和Map。

总体来看Spring的配置属于静态配置,缺少动态刷新(例如定期修改数据库密码),版本管理等能力,在选型时要结合实际业务场景判断是否满足要求。


其他阅读:

萌新快速成长之路
如何编写软件设计文档
Spring Cache架构、机制及使用
布隆过滤器适配Spring Cache及问题与解决策略
JAVA编程思想(一)通过依赖注入增加扩展性
JAVA编程思想(二)如何面向接口编程
JAVA编程思想(三)去掉别扭的if,自注册策略模式优雅满足开闭原则
Java编程思想(七)使用组合和继承的场景
JAVA基础(一)简单、透彻理解内部类和静态内部类
JAVA基础(二)内存优化-使用Java引用做缓存
JAVA基础(三)ClassLoader实现热加载
JAVA基础(五)函数式接口-复用,解耦之利刃

相关推荐
shuair4 分钟前
tomcat的accept-count、max-connections、max-threads三个参数的含义
java·tomcat
画船听雨眠aa6 分钟前
SSM项目本地Tomcat部署
java·tomcat
极客先躯17 分钟前
高级java每日一道面试题-2025年01月24日-框架篇[SpringMVC篇]-SpringMVC常用的注解有哪些?
java·springmvc·常用的注解
咕德猫宁丶21 分钟前
Spring Boot 邂逅Netty:构建高性能网络应用的奇妙之旅
java·spring boot·后端
_板栗_24 分钟前
Java8 - flatMap() 介绍
java·stream
C++小厨神26 分钟前
C#语言的函数实现
开发语言·后端·golang
计算机学姐34 分钟前
基于微信小程序的网上订餐管理系统
java·vue.js·spring boot·mysql·微信小程序·小程序·intellij-idea
博一波36 分钟前
【设计模式-行为型】访问者模式
java·设计模式·访问者模式
计算机-秋大田1 小时前
基于JAVA的微信点餐小程序设计与实现(LW+源码+讲解)
java·开发语言·后端·微信·小程序·课程设计
llp11101 小时前
基于java线程池和EasyExcel实现数据异步导入
java·开发语言