Spring中读取配置属性的方式和SpringBoot自动配置重要特性

一、引言

SpringBoot的自动配置中,有两个分量很重的注解 @ConfigurationProperties@EnableConfigurationProperties。这两个注解能干嘛呢?它们的原理又是什么呢?下面本文就来学习一下。

在学习@ConfigurationProperties之前,先来回想一下在Spring中读取配置属性的方式有哪些?是不是立刻就会想到@Value注解?对,就是这个注解。

下面对@Value@PropertySource@ConfigurationProperties等相关注解进行学习介绍。

二、属性赋值相关注解

1、@Value

@Value注解非常有用,它的用法也非常多,但这里只介绍一种情况,也是本人在开发中最常用的情况,至于其他使用方式,例如:普通字符串的注入和表达式的注入意义不是很大,此处不做过多介绍。

@Value注解最常用的一种方式,就是将配置文件中自定义的属性值注入到特定属性中,下面直接上代码。
配置文件测试类及结果
解释一下:application.properties配置文件中,自定义了一个属性person.name,通过@Value注解,就可以将这个配置文件中自定义的值映射到代码中的属性上。

注意:此处@Value的值还可以从系统变量中取值。

上面这种方式,就是本人在日常开发中最常用的方式。那么什么情况下会用到这个@Value注解呢?可配置属性。例如,现在有个功能是要接受客户端上传上来的文件,存放文件的目录要求可以动态配置,不能在代码中写死,是不是想到这个注解了?

这里需要注意的是:在使用${ key }去获取值时,如果 key 找不到,启动会失败,这样是不对的,我们不能因为一个属性没有配置而让项目无法启动。所以,我们可以给它一个默认值,就如下面的配置,如果person.name拿不到值,就用scorpios作为默认值。

    @Value("${person.name:scorpios}")
    String name;
2、@PropertySource:加载配置属性源

@PropertySource注解也是非常非常的强大,通过@PropertySource注解可以把配置文件加载进来,然后使用@Value获取其中的属性值。

在上面的例子,@Value注解获取属性值是从application.properties配置文件中获取的。如果现在我们不在配置文件中配置这些属性,而是单独放在一个文件中,怎么办呢?看下面代码:

@Configuration
@PropertySource("classpath:jdbc.properties")
public class JdbcConfig {

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

    @Value("${jdbc.password}")
    private String password;

    public String print(){
        return name + "-" + password;
    }

在这里插入图片描述在这里插入图片描述
是不是不用讲就已经明白@PropertySource的使用了?哈哈~~~~~
下面来对@PropertySource各属性介绍:

  1. value:数组。用于指定配置文件的位置。支持classpath:file:等前缀, Spring发现是classpath开头的,因此最终使用的是Resource的子类ClassPathResource。如果是file开头的,则最终使用的类是FileSystemResource

  2. ignoreResourceNotFound:默认值false。表示如果没有找到文件就报错,若改为true就不报错。建议保留false。

  3. encoding:加载进来的编码。一般不用设置,可以设置为UTF-8等等

  4. factory:默认的值为DefaultPropertySourceFactory.class

需要注意的是PropertySourceFactory的加载时机早于SpringIOC容器,因此实现上不能依赖于Spring的IOC。(能理解最好,要不然仅当了解就好)
3、@ConfigurationProperties

注意:上面两个注解都是Spring Framwork提供的功能。而@ConfigurationPropertiesSpring Boot提供的。包括@EnableConfigurationProperties也是Spring Boot才有的。它在自动化配置中起到了非常关键的作用。

@ConfigurationProperties的作用就是,它可以把配置文件中的配置信息自动封装成对应的实体类,来看一下例子。(☆☆☆☆☆)

// application.properties配置文件中的配置属性

test.people.name=scorpios
test.people.age=30
test.people.address[0]=上海
test.people.address[1]=南京
test.people.address[2]=苏州
// 要封装的实体类
@Component // 注意一下这个注解!!!!
@ConfigurationProperties(prefix = "test.people")
public class People {
    private String name;
    private Integer age;
    private List<String> address;
	// setter / getter / toString 方法省略
}

在这里插入图片描述
同样的问题,如果不在application.properties配置文件中指定这些属性值,而是需要额外指定配置文件,就需要结合@PropertySource注解使用,结果依然可以。

@Component // 注意一下这个注解!!!!
@ConfigurationProperties(prefix = "test.people")
@PropertySource(value = {"classpath:people.properties"})
public class People {

    private String name;
    private Integer age;
    private List<String> address;
    }
在读Spring源码时,关注ConfigurationPropertiesBindingPostProcessor后置处理器,它会对标注@ConfigurationProperties注解的Bean进行属性值配置。

上面的代码中,在使用@ConfigurationProperties注解时,特意强调了一下要加@Component注解。如果不加@Component这个注解,在启动程序时会报错。这能说明什么问题呢?

这能说明:@ConfigurationProperties注解主要作用是把properties配置文件赋值给SpringIOC容器中的Bean的,这个注解作用的前提条件就是这个实体类必须已经转化为了Bean,并且已经存在与SpingIOC容器中。

但是!!!当我们在看SpringBoot自动配置源码时,并没有看到属性类上面加了这个@Component注解!!!(不信的话,可以去查看各个自动配置类需要用到的对应***Properties类,这里我只放两个类),这是为什么呢?这就涉及到SpringBoot的自动装配原理了。
在这里插入图片描述
在这里插入图片描述
好了,下面要引入@EnableConfigurationProperties注解,这个注解的作用是让@ConfigurationProperties注解生效。什么意思呢?

就是说如果我们在需要映射的实体类上只标注了@ConfigurationProperties注解,但是这个实体类并没有转化为Bean存在于SpringIOC容器中,这个注解是没有用的(会报错),也就是说属性绑定会失败。(能理解此处的Bean的意思么?)

这里先说一下,用@EnableConfigurationProperties注解会将对应的实体类转为Bean加入到SpringIOC容器中,如下所示。至于为什么?且听下回分解。
在这里插入图片描述

终于讲完啦。。。。。理解了么?

三、小结

简单总结一下

1、@ConfigurationProperties注解 是将application配置文件的某类名下所有的属性值,自动封装到实体类中。这个注解作用的前提条件就是,实体类已经转化为Bean存在于SpringIOC容器中。

2、@EnableConfigurationProperties注解的作用是让@ConfigurationProperties注解生效。也就是让@ConfigurationProperties注解绑定的实体类转为为Bean交给SpingIOC容器管理。从而让@ConfigurationProperties注解生效。

3、@Value 是将application配置文件中,所需要的某个属性值,封装到Java代码中以供使用。


补充

@ImportResource注解

此注解的作用是导入Spring的配置文件,让配置文件里面的内容生效。此注解常常在老的Spring项目SpringBoot项目迁移过程中使用。因为 Spring Boot 里面根本就没有Spring的配置文件,我们自己编写的配置文件,SpringBoot 也不能自动识别。

所以想让Spring的配置文件生效,就需要使用@ImportResource注解,此注解标注在一个配置类上即可。

// 导入Spring的配置文件让其生效
@ImportResource(locations = {"classpath:beans.xml"}) 
@SpringBootApplication
public class SpringBootDemoApplication {
	public static void main(String[] args) {
		SpringApplication.run(SpringBootDemoApplication.class, args);
	}
}
发布了123 篇原创文章 · 获赞 230 · 访问量 19万+

猜你喜欢

转载自blog.csdn.net/zxd1435513775/article/details/103661672