SpringBoot中读取配置的几种方式

个人博客地址

一、介绍

在SpringBoot项目中,我们使用application.yml或者application.properties文件,那么在如何读取其中的配置参数呢?

有以下这么几种

  1. 使用@Value注解
  2. 使用@ConfigurationProperties注解
  3. 使用@PropertySource+@Value注解
  4. 使用@PropertySource+@ConfigurationProperties注解
  5. 使用Environment.getProperty()

前面两种大家都很熟悉,也在常常使用,剩下这几个就比较陌生了,一起来看看吧。

二、方法

1)@Value注解

假如我们有这样的一个application.yml配置文件

server:
  port: 8888

对于这样单条的配置,我们可以采用@Value去进行获取

package com.banmoon.test.job;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

@Slf4j
@Component
public class TestJob {

    @Value("${server.port}")
    private Integer port;

    @Scheduled(cron = "0/3 * * * * *")
    public void start(){
        log.info("端口号:{}", port);
    }

}

image-20220408193720017

优缺点也很明显,简单快捷,但只能单个单个获取,如果要获取一批配置就会显得十分繁琐


注意,@Value不能用来修饰静态属性,会读取不到,导致属性为Null的

修改一下上面的属性,让它变成静态属性

package com.banmoon.test.job;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

@Slf4j
@Component
public class TestJob {

    @Value("${server.port}")
    private static Integer port;

    @Scheduled(cron = "0/3 * * * * *")
    public void start(){
        log.info("端口号:{}", port);
    }

}

image-20220408194155386

那么,如果非要使用静态属性该怎么办呢?虽然不建议使用,哎可以改成这样。

package com.banmoon.test.job;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

@Slf4j
@Component
public class TestJob {

    private static Integer port;

    @Value("${server.port}")
    public void setPort(Integer port) {
        TestJob.port = port;
    }

    @Scheduled(cron = "0/3 * * * * *")
    public void start(){
        log.info("端口号:{}", port);
    }

}

聪明的你马上就知道了是怎么一回事了,这和Bean的初始化有关。如果不懂,还是不要使用了,不然说不定获取到的还是一个Null

image-20220408194533045

2)@ConfigurationProperties注解

这个注解也十分熟悉,它可以将配置信息映射成我们的一个Bean,通过这个Bean,我们就可以获取到配置的信息啦。它解决上面@Value只能一个一个去获取配置的繁琐痛点。

假设我们现在有这样的一个配置

user:
  name: banmoon
  age: 18
  sex:friends:
    - 阿超
    - 九月

那么,我们只需要这样做,就可以映射成我们这个Bean了

package com.banmoon.test.config;

import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

import java.io.Serializable;
import java.util.List;

@Data
@Component
@ConfigurationProperties(prefix = "user")
public class UserProperties implements Serializable {

    private String name;

    private Integer age;

    private String sex;

    private List<String> friends;

}

我们再获取一下这个Bean,打印一下里面的信息

package com.banmoon.test.job;

import com.banmoon.test.config.UserProperties;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;

@Slf4j
@Component
public class TestJob {

    @Autowired
    private UserProperties userProperties;

    @PostConstruct
    public void start(){
        log.info("user配置信息:{}", userProperties);
    }

}

image-20220408195819605

这个注解比起@Value,编码的效率就快了不少

3)@PropertySource+@Value注解

在开发中,我们不只有application.yml一个配置文件,我们可能有多个,如果要加载其他的配置文件时。

@PropertySource注解就派上用场了,指定了加载哪个配置文件作为配置源。

假设我们现在多了一个user.properties的配置文件

other.port=2333

只需要小改,在类上添加@PropertySource注解,指定加载这个配置文件即可。

由于@PropertySource只是指定了加载哪个配置文件,所以它还需要搭配@Value注解进行使用

package com.banmoon.test.job;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.PropertySource;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

@Slf4j
@Component
@PropertySource("classpath:user.properties")
public class TestJob {

    @Value("${other.port}")
    private String port;

    @Scheduled(cron = "0/3 * * * * *")
    public void start(){
        log.info("其他端口:{}", port);
    }

}

image-20220408222910402

4)@PropertySource+@ConfigurationProperties注解

既然@PropertySource注解是指定加载某个配置文件,需要搭配@Value使用,那么它也可以搭配@ConfigurationProperties注解进行使用。

同样在user.properties文件中

user.name=banmoon
user.age=18
user.sex=男
user.friends[0]=钟离
user.friends[1]=巴尔

我们只需要在类上指定上@PropertySource即可

package com.banmoon.test.config;

import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Component;

import java.io.Serializable;
import java.util.List;

@Data
@Component
@PropertySource("classpath:user.properties")
@ConfigurationProperties(prefix = "user")
public class UserProperties implements Serializable {

    private String name;

    private Integer age;

    private String sex;

    private List<String> friends;

}

在使用上,同上,这里代码就不贴出来了

image-20220408231145746

5)Environment.getProperty()

最后一种,见都没有见过,环境获取参数?

同样测试一下,获取个端口看看

package com.banmoon.test.job;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

@Slf4j
@Component
public class TestJob {

    @Autowired
    private Environment environment;

    @Scheduled(cron = "0/3 * * * * *")
    public void start(){
        log.info("【environment】当前端口:{}", environment.getProperty("server.port"));
    }

}

image-20220408234442334

此方法,支持动态的获取需要的参数,虽然平常不常用,但还是做一下记录。

三、@PropertySource加载yml文件

在上面的示例中,@PropertySource加载的是properties文件,不代表它只能加载properties文件

比如说这次我们添加一个example.yml文件

example:
	name: 半月无霜

在加载时,我们只需要这样指定就行

package com.banmoon.test.job;

import com.banmoon.test.config.YamlPropertySourceFactory;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.PropertySource;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

@Slf4j
@Component
@PropertySource(value = "classpath:example.yml", factory = YamlPropertySourceFactory.class)
public class TestJob {

    @Value("${example.name}")
    private String name;

    @Scheduled(cron = "0/3 * * * * *")
    public void start(){
        log.info("加载其他yaml文件:{}", name);
    }

}

image-20220409093416702

至于YamlPropertySourceFactory.java,这是我们自己实现的一个类,如下可以直接使用

package com.banmoon.test.config;

import org.springframework.boot.env.YamlPropertySourceLoader;
import org.springframework.core.env.PropertySource;
import org.springframework.core.io.support.DefaultPropertySourceFactory;
import org.springframework.core.io.support.EncodedResource;

import java.io.IOException;
import java.util.List;

public class YamlPropertySourceFactory extends DefaultPropertySourceFactory {

    @Override
    public PropertySource<?> createPropertySource(String name, EncodedResource resource) throws IOException {
        if (resource == null)
            return super.createPropertySource(name, resource);
        List<PropertySource<?>> sources = new YamlPropertySourceLoader()
                .load(resource.getResource().getFilename(), resource.getResource());
        return sources.get(0);
    }

}

四、最后

我是半月,祝你幸福!!!

  • 20
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值