我的编程空间,编程开发者的网络收藏夹
学习永远不晚

使用@PropertySource读取配置文件通过@Value进行参数注入

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

使用@PropertySource读取配置文件通过@Value进行参数注入

@PropertySource读取配置文件通过@Value参数注入

有参数文件如下test.properties

project.author=wpfc
project.create_time=2018/3/29

在系统中读取对应的数据,并注入到属性中

@Configuration
@ComponentScan("cn.edu.ntu")
@PropertySource("classpath:test.properties")
public class ElConfig {
 
    @Value("#{systemProperties['os.name']}")
    private String osName;
    
    //要想使用@Value 用${}占位符注入属性,这个bean是必须的(PropertySourcesPlaceholderConfigurer),
    //这个就是占位bean,
    //另一种方式是不用value直接用Envirment变量直接getProperty('key')  
    @Value("${project.author}")
    public String author;
    
    @Autowired
    private Environment environment;
    
    //You need this if you use @PropertySource + @Value
    @Bean
    public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
       return new PropertySourcesPlaceholderConfigurer();
    }
    
    public void printProperties(){
        System.out.println("os name : " + osName);
        System.out.println("author  : " + author);
        System.out.println("env     : " + environment.getProperty("project.create_time"));
    }    
}

测试方法:

public class MainApplication {
    public static void main(String[] args){
        AnnotationConfigApplicationContext context = null;
        context = new AnnotationConfigApplicationContext(ElConfig.class);
        ElConfig bean = context.getBean(ElConfig.class);
        bean.printProperties();
    }    
}

测试结果:

os name : Windows 7
author  : wpfc
env     : 2018/3/29

  • @Import引入javaConfig配置的配置类
  • @ImportResource引入xml对应的配置文件

Spring读取配置@Value、@PropertySource、@ConfigurationProperties使用

Spring (Boot)获取参数的方式有很多,其中最被我们熟知的为@Value了,它不可谓不强大。

今天就针对我们平时最长使用的@Value,以及可能很少人使用的@PropertySource、@ConfigurationProperties等相关注解进行一个详细的扫盲,希望能够帮助到到家,使用起来更加顺畅

@Value

@Value注解的注入非常强大,可以借助配置文件的注入、也可以直接注入

注入普通字符串

    @Value("normal")
    private String normal; // normal (显然这种注入的意义不大)

注入操作系统属性

@Value("#{systemProperties['os.name']}")
    private String systemPropertiesName; 
//效果等同于  是因为spring模版把系统变量否放进了Enviroment
@Value("${os.name}")
    private String systemPropertiesName;

注入表达式结果

@Value("#{ T(java.lang.Math).random() * 100.0 }")
    private double randomNumber; //41.29185128620939

注入其它Bean的属性:Person类的name属性

    @Bean
    public Person person() {
        Person person = new Person();
        person.setName("fangshixiang");
        return person;
    }
 
//注入属性
    @Value("#{person.name}")
    private String personName;
 
    @Test
    public void contextLoads() {
        System.out.println(personName); //fangshixiang
    }

注入文件资源

在resources下放置一个jdbc.properties配置文件。然后可以直接注入

    @Value("classpath:jdbc.properties")
    private Resource resourceFile; // 注入文件资源
 
    @Test
    public void contextLoads() throws IOException {
        System.out.println(resourceFile); //class path resource [jdbc.properties]
        String s = FileUtils.readFileToString(resourceFile.getFile(), StandardCharsets.UTF_8);
        System.out.println(s);
        //输出:
        //db.username=fangshixiang
        //db.password=fang
        //db.url=jdbc:mysql://localhost:3306/mytest
        //db.driver-class-name=com.mysql.jdbc.Driver
    }

注入Url资源

    @Value("http://www.baidu.com")
    private Resource testUrl; // 注入URL资源 
 
    @Test
    public void contextLoads() {
        System.out.println(testUrl); //URL [http://www.baidu.com]
    }

@Value中$和#的区别

语法:

${ properties }和#{ SpEL }的语法区别

${ property : default_value }

#{ obj.property? : default_value } 表示SpEl表达式通常用来获取bean的属性,或者调用bean的某个方法。当然还有可以表示常量

正常使用的情况,这里不做过多的介绍了,现在介绍一些异常情况

${ properties }`:这种比较简单,如果key找不到,启动会失败。如果找不到的时候也希望正常启动,可以采用冒号+默认值的方式

#{ obj.property? : default_value }

    @Value("#{person}")
    private Person value;
 
    @Test
    public void contextLoads() {
        System.out.println(value); //Person(name=fangshixiang, age=null, addr=null, hobby=null)
    }

我们发现这个很强大,可以直接把容器的里的一个对象直接注入进来。只是我们可能一般不这么做。

如果改成person1,在容器里找不到这个bean,也是会启动报错的。@Value("#{person1?:null}")这样也是不行的,因为person1找不到就会报错  

    @Value("#{person.name}")
    private String personName;
 
    @Value("#{person.age}")
    private String perAge;
 
    //注入默认值
    @Value("#{person.age?:20}")
    private String perAgeDefault;
 
    //如果age22这个key根本就不存在,启动肯定会报错的
    //@Value("#{person.age22?:20}")
    //private String perAgeDefault22;
 
    @Test
    public void contextLoads() {
        System.out.println(personName); //fangshixiang
        System.out.println(perAge); //null
        System.out.println(perAgeDefault); //20
    }

获取级联属性,下面两种方法都是ok的:

 
    @Value("#{person.parent.name}")
    private String parentName1;
 
    @Value("#{person['parent.name']}")
    private String parentName2;
 
    @Test
    public void contextLoads() {
        System.out.println(parentName1); //fangshixiang
        System.out.println(parentName2); //fangshixiang
    }

二者结合使用:#{ ‘${}’ }

注意结合使用的语法和单引号,不能倒过来。

两者结合使用,可以利用SpEL的特性,写出一些较为复杂的表达式,如:

    @Value("#{'${os.name}' + '_' +  person.name}")
    private String age; 
 
    @Test
    public void contextLoads() {
        System.out.println(age); //Windows 10_fangshixiang
    }

@PropertySource:加载配置属性源

此注解也是非常非常的强大,用好了,可以很好的实现配置文件的分离关注,大大提高开发的效率,实现集中化管理

最简单的应用,结合@Value注入属性值(也是最常见的应用)

通过@PropertySource把配置文件加载进来,然后使用@Value获取

@Configuration
@PropertySource("classpath:jdbc.properties")
public class PropertySourceConfig {
 
    @Value("${db.url}")
    private String dbUrl;
 
    @PostConstruct
    public void postConstruct() {
        System.out.println(dbUrl); //jdbc:mysql://localhost:3306/mytest
    }
}

@PropertySource各属性介绍

  • value:数组。指定配置文件的位置。支持classpath:和file:等前缀 Spring发现是classpath开头的,因此最终使用的是Resource的子类ClassPathResource。如果是file开头的,则最终使用的类是FileSystemResource
  • ignoreResourceNotFound:默认值false。表示如果没有找到文件就报错,若改为true就不报错。建议保留false
  • encoding:加载进来的编码。一般不用设置,可以设置为UTF-8等等
  • factory:默认的值为DefaultPropertySourceFactory.class。
	@Override
	public PropertySource<?> createPropertySource(String name, EncodedResource resource) throws IOException {
		return (name != null ? new ResourcePropertySource(name, resource) : new ResourcePropertySource(resource));
	}

源码其实也没什么特别的。其重难点在于:

1、DefaultPropertySourceFactory什么时候被Spring加载呢?

2、name和resource都是什么时候被赋值进来的?

本文抛出这两个问题,具体原因会在后续分析源码的相关文章中有所体现。

需要注意的是PropertySourceFactory的加载时机早于Spring Beans容器,因此实现上不能依赖于Spring的IOC。

@PropertySource多环境配置以及表达式使用(spring.profiles.active)

方法一:可以这么配置

@PropertySource(“classpath:jdbc-${spring.profiles.active}.properties”)

程序员在开发时不需要关心生产环境数据库的地址、账号等信息,一次构建即可在不同环境中运行

@ConfigurationProperties

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

ConfigurationPropertiesBindingPostProcessor会对标注@ConfigurationProperties注解的Bean进行属性值的配置。

有时候有这样子的情景,我们想把配置文件的信息,读取并自动封装成实体类,这样子,我们在代码里面使用就轻松方便多了,这时候,我们就可以使用@ConfigurationProperties,它可以把同类的配置信息自动封装成实体类

该注解在Spring Boot的自动化配置中得到了大量的使用

如SpringMVC的自动化配置:

@ConfigurationProperties(prefix = "spring.mvc")
public class WebMvcProperties {}
 
//加载方式
	@Configuration
	@Conditional(DefaultDispatcherServletCondition.class)
	@ConditionalOnClass(ServletRegistration.class)
	// 此处采用这个注解,可议把WebMvcProperties这个Bean加载到容器里面去~~~
	// WebMvcProperties里面使用了`@ConfigurationProperties(prefix = "spring.mvc")`
	@EnableConfigurationProperties(WebMvcProperties.class) //加载MVC的配置文件
	protected static class DispatcherServletConfiguration {}

似乎我们能看出来一些该注解的使用方式。

说明:这里说的两种,只是说的最常用的。其实只要能往容器注入Bean,都是一种方式,比如上面的@EnableConfigurationProperties方式也是ok的

关于@EnableConfigurationProperties的解释,在注解驱动的Spring相关博文里会有体现

加在类上,需要和@Component注解,结合使用.代码如下

com.example.demo.name=${aaa:hi}
com.example.demo.age=11
com.example.demo.address[0]=北京  # 注意数组 List的表示方式 Map/Obj的方式各位可以自行尝试
com.example.demo.address[1]=上海
com.example.demo.address[2]=广州
com.example.demo.phone.number=1111111

java代码:

@Component
@ConfigurationProperties(prefix = "com.example.demo")
public class People {
 
    private String name;
    private Integer age;
    private List<String> address;
    private Phone phone;
}   

通过@Bean的方式进行声明,这里我们加在启动类即可,代码如下

   @Bean
    @ConfigurationProperties(prefix = "com.example.demo")
    public People people() {
        return new People();
    }

此些方式并不需要使用@EnableConfigurationProperties去开启它。

细节:Bean的字段必须有get/set方法,请注意~~~

另外还有一种结合@PropertySource使用的方式,可谓完美搭配

@Component
@PropertySource("classpath:config/object.properties")
@ConfigurationProperties(prefix = "obj")
public class ObjectProperties {}

其余属性见名之意,这里一笔带过:

  • ignoreInvalidFields
  • ignoreNestedProperties
  • ignoreUnknownFields

简单理解:

  • @ConfigurationProperties 是将application配置文件的某类名下所有的属性值,自动封装到实体类中。
  • @Value 是将application配置文件中,所需要的某个属性值,封装到java代码中以供使用。

应用场景不同:

如果只是某个业务中需要获取配置文件中的某项值或者设置具体值,可以使用@Value;

如果一个JavaBean中大量属性值要和配置文件进行映射,可以使用@ConfigurationProperties;

以上为个人经验,希望能给大家一个参考,也希望大家多多支持编程网。

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

使用@PropertySource读取配置文件通过@Value进行参数注入

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

使用@Value注解从配置文件中读取数组的方法

本篇内容主要讲解“使用@Value注解从配置文件中读取数组的方法”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“使用@Value注解从配置文件中读取数组的方法”吧!@Value注解从配置文件读取数
2023-06-20

properties配置文件如何使用Spring Boot进行读取

这篇文章给大家介绍properties配置文件如何使用Spring Boot进行读取,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。在SpringApplication类中: private ConfigurableE
2023-05-31

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录