当前位置:   article > 正文

springboot修改配置文件属性值_SpringBoot注入数据的方式

springboot启动后重写bean的属性值
点击上方☝ Java编程技术乐园,轻松关注! 及时获取有趣有料的技术文章

做一个积极的人编码、改bug、提升自己

我有一个乐园,面向编程,春暖花开!

2065cab34ae17b743fe1d44fde8a6218.png

作者: 胖先森(来自:掘金)

原文链接:https://juejin.im/post/5c1f119ee51d4568f03b8857

关于注入数据说明

def9ac17a31ef2924fe7944ae56dff40.png

1.不通过配置文件注入数据

通过@Value将外部的值动态注入到Bean中,使用的情况有:

  • 注入普通字符串

  • 注入操作系统属性

  • 注入表达式结果

  • 注入其他Bean属性:注入Student对象的属性name

  • 注入文件资源

  • 注入URL资源

辅助代码

package com.hannpang.model;import org.springframework.beans.factory.annotation.Value;import org.springframework.stereotype.Component;@Component(value = "st")//对student进行实例化操作public class Student {    @Value("悟空")    private String name;    public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    }}

测试@Value的代码

package com.hannpang.model;import org.springframework.beans.factory.annotation.Value;import org.springframework.core.io.Resource;import org.springframework.stereotype.Component;@Componentpublic class SimpleObject {    @Value("注入普通字符串")    private String normal;    //关于属性的KEY可以查看System类说明    @Value("#{systemProperties['java.version']}")//-->使用了SpEL表达式    private String systemPropertiesName; // 注入操作系统属性    @Value("#{T(java.lang.Math).random()*80}")//获取随机数    private double randomNumber; //注入表达式结果    @Value("#{1+2}")    private double sum//注入表达式结果 1+2的求和    @Value("classpath:os.yaml")    private Resource resourceFile; // 注入文件资源    @Value("http://www.baidu.com")    private Resource testUrl; // 注入URL资源    @Value("#{st.name}")    private String studentName;    //省略getter和setter方法    @Override    public String toString() {        return "SimpleObject{" +                "normal='" + normal + ''' +                ", systemPropertiesName='" + systemPropertiesName + ''' +                ", randomNumber=" + randomNumber +                "sum=" + sum +                ", resourceFile=" + resourceFile +                ", testUrl=" + testUrl +                ", studentName='" + studentName + ''' +                '}';    }}

Spring的测试代码

package com.hannpang;import com.hannpang.model.SimpleObject;import org.junit.Test;import org.junit.runner.RunWith;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.boot.test.context.SpringBootTest;import org.springframework.test.context.junit4.SpringRunner;@RunWith(SpringRunner.class)@SpringBootTestpublic class Demo04BootApplicationTests {    @Autowired    private SimpleObject so;    @Test    public void contextLoads()  {        System.out.println(so);    }}
运行结果为:SimpleObject{normal='注入普通字符串', systemPropertiesName='1.8.0_172', randomNumber=56.631954541947266sum=3.0, resourceFile=class path resource [os.yaml], testUrl=URL [http://www.baidu.com], studentName='悟空'}

2.通过配置文件注入数据

通过@Value将外部配置文件的值动态注入到Bean中。配置文件主要有两类:

  • application.properties、application.yaml   application.properties在spring boot启动时默认加载此文件

  • 自定义属性文件。自定义属性文件通过@PropertySource加载。@PropertySource可以同时加载多个文件,也可以加载单个文件。如果相同第一个属性文件和第二属性文件存在相同key,则最后一个属性文件里的key启作用。加载文件的路径也可以配置变量,如下文的${anotherfile.configinject},此值定义在第一个属性文件config.properties

  • 在application.properties中加入如下测试代码

app.name=一步教育
  • 在resources下面新建第一个属性文件config.properties内容如下

book.name=西游记anotherfile.configinject=system
  • 在resources下面新建第二个属性文件config_system.properties内容如下

我的目的是想system的值使用第一个属性文件中定义的值

book.name.author=吴承恩

下面通过@Value(“${app.name}”)语法将属性文件的值注入bean属性值,详细代码见:

package com.hannpang.test;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.beans.factory.annotation.Value;import org.springframework.context.annotation.PropertySource;import org.springframework.core.env.Environment;import org.springframework.stereotype.Component;@Component@PropertySource(value = {"classpath:config.properties","classpath:config_${anotherfile.configinject}.properties"})public class LoadPropsTest {    @Value("${app.name}")    private String appName; // 这里的值来自application.properties,spring boot启动时默认加载此文件    @Value("${book.name}")    private String bookName; // 注入第一个配置外部文件属性    @Value("${book.name.author}")    private String author; // 注入第二个配置外部文件属性    @Autowired    private Environment env;  // 注入环境变量对象,存储注入的属性值    //省略getter和setter方法    public void setAuthor(String author) {        this.author = author;    }    @Override    public String toString(){        StringBuilder sb = new StringBuilder();        sb.append("bookName=").append(bookName).append("")                .append("author=").append(author).append("")                .append("appName=").append(appName).append("")                .append("env=").append(env).append("")                // 从eniroment中获取属性值                .append("env=").append(env.getProperty("book.name.author")).append("");        return sb.toString();    }}

测试代码

package com.hannpang;import com.hannpang.model.SimpleObject;import com.hannpang.test.LoadPropsTest;import org.junit.Test;import org.junit.runner.RunWith;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.boot.test.context.SpringBootTest;import org.springframework.test.context.junit4.SpringRunner;@RunWith(SpringRunner.class)@SpringBootTestpublic class Demo04BootApplicationTests {    @Autowired    private LoadPropsTest lpt;    @Test    public void loadPropertiesTest()  {        System.out.println(lpt);    }}
运行结果为:bookName=西游记author=吴承恩appName=一步教育env=StandardEnvironment {activeProfiles=[], defaultProfiles=[default], propertySources=[ConfigurationPropertySourcesPropertySource {name='configurationProperties'}, MapPropertySource {name='Inlined Test Properties'}, MapPropertySource {name='systemProperties'}, OriginAwareSystemEnvironmentPropertySource {name='systemEnvironment'}, RandomValuePropertySource {name='random'}, OriginTrackedMapPropertySource {name='applicationConfig: [classpath:/application.properties]'}, ResourcePropertySource {name='class path resource [config_system.properties]'}, ResourcePropertySource {name='class path resource [config.properties]'}]}env=吴承恩

3. #{...}和${...}的区别演示

A.${…}的用法

{}里面的内容必须符合SpEL表达式,通过@Value(“${app.name}”)可以获取属性文件中对应的值,但是如果属性文件中没有这个属性,则会报错。可以通过赋予默认值解决这个问题,如@Value("${app.name:胖先森}")

部分代码

// 如果属性文件没有app.name,则会报错//  @Value("${app.name}")//  private String name;// 使用app.name设置值,如果不存在则使用默认值@Value("${app.name:胖先森}")private String name;

B.#{...}的用法

部分代码直接演示

// SpEL:调用字符串Hello World的concat方法@Value("#{'Hello World'.concat('!')}")private String helloWorld;// SpEL: 调用字符串的getBytes方法,然后调用length属性@Value("#{'Hello World'.bytes.length}")private String helloWorldbytes;

C.#{...}${...}混合使用

${...}和#{...}可以混合使用,如下文代码执行顺序:通过${server.name}从属性文件中获取值并进行替换,然后就变成了 执行SpEL表达式{‘server1,server2,server3’.split(‘,’)}。

// SpEL: 传入一个字符串,根据","切分后插入列表中, #{}和${}配置使用(注意单引号,注意不能反过来${}在外面,#{}在里面)@Value("#{'${server.name}'.split(',')}")private List servers;

在上文中在#{}外面,${}在里面可以执行成功,那么反过来是否可以呢${}在外面,#{}在里面,如代码

// SpEL: 注意不能反过来${}在外面,#{}在里面,这个会执行失败@Value("${#{'HelloWorld'.concat('_')}}")private List<String> servers2;
答案是不能。因为spring执行${}是时机要早于#{}。在本例中,Spring会尝试从属性中查找#{‘HelloWorld’.concat(‘_’)},那么肯定找到,由上文已知如果找不到,然后报错。所以${}在外面,#{}在里面是非法操作

D.用法总结

  • #{…} 用于执行SpEl表达式,并将内容赋值给属性

  • ${…} 主要用于加载外部属性文件中的值

  • #{…} 和${…} 可以混合使用,但是必须#{}外面,${}在里面

4.@Value获取值和@ConfigurationProperties获取值比较

@ConfigurationProperties@Value
功能批量注入配置文件中的属性一个个指定
松散绑定(松散语法)支持不支持
SpEL不支持支持
JSR303数据校验支持不支持
复杂类型封装支持不支持

配置文件yml还是properties他们都能获取到值;

  • 如果说,我们只是在某个业务逻辑中需要获取一下配置文件中的某项值,使用@Value;

  • 如果说,我们专门编写了一个javaBean来和配置文件进行映射,我们就直接使用@ConfigurationProperties;

关于数据校验的部分代码

@Component@ConfigurationProperties(prefix = "person")@Validatedpublic class Person {   //lastName必须是邮箱格式    @Email    private String lastName;

5. @ImportResource引入配置文件

不推荐的使用方式

Spring Boot里面没有Spring的配置文件,我们自己编写的配置文件,也不能自动识别;

想让Spring的配置文件生效,加载进来;@ImportResource标注在一个配置类上

@ImportResource(locations = {"classpath:beans.xml"})导入Spring的配置文件让其生效

编写配置文件信息

<?xml  version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">    <bean id="helloService" class="com.hanpang.springboot.service.HelloService">bean>beans>

大概了解就好,我们基本上不使用这种方式

6.@Configuration注解

SpringBoot推荐给容器中添加组件的方式;推荐使用全注解的方式

1、配置类@Configuration作用于类上,相当于一个xml配置文件

2、使用@Bean给容器中添加组件,作用于方法上

/** * @Configuration:指明当前类是一个配置类;就是来替代之前的Spring配置文件 * * 在配置文件中用标签添加组件 *  */@Configurationpublic class MyAppConfig {    //将方法的返回值添加到容器中;容器中这个组件默认的id就是方法名    @Bean    public HelloService helloService02(){        System.out.println("配置类@Bean给容器中添加组件了...");        return new HelloService();    }}

使用Bean注入太麻烦,我们更加喜欢使用扫描的方式

import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.ComponentScan;import org.springframework.context.annotation.Configuration;import com.wx.dao.IUserDao;import com.wx.dao.UserDaoImpl;//通过该注解来表明该类是一个Spring的配置,相当于一个传统的ApplicationContext.xml@Configuration//相当于配置文件里面的标签,扫描这些包下面的类的注解@ComponentScan(basePackages="com.hanpang.dao,com.hanpang.service")public class SpringConfig {    // 通过该注解来表明是一个Bean对象,相当于xml中的    //bean的id值默认是方法名userDao    /*    @Bean    public HelloService helloService02(){        System.out.println("配置类@Bean给容器中添加组件了...");        return new HelloService();    }    */}

附录

随机数

${random.value}、${random.int}、${random.long}${random.int(10)}、${random.int[1024,65536]}
4ed1e9f9ab9380eca9f0f0eb650b2e4f.gif

往期精彩回顾

fd20556e8f54d3a6119bc4d9ae2a8975.gifSpring中@Autowired、@Resource和@Inject注解的使用和区别

掌握Spring常用注解【一】

一文学会Java死锁和CPU 100% 问题的排查技巧

【面试】MySQL 中NULL和空值的区别?

Mybatis 批量插入引发的血案

Java内存管理-Stackoverflow问答-Java是传值还是传引用?(十一)

你有遇到过MySQL因大小写敏感导致的问题吗

MySQL 的COUNT(x)性能怎么样?

共勉:作为一名程序员你应该怎么提一个高质量的问题?

c5777084a951eed302b8d619715158d2.png

5cd8ab8db282893cbf765981a166834d.png欢迎长按下图关注公众号5cd8ab8db282893cbf765981a166834d.png

f21d86cfa1c9986cf7cf3dbf873ee02f.png

后台回复【资源】,获取珍藏干货!

99.9%的伙伴都很喜欢1a109a6ff7ad9ad6c9b0b19a765a3f4b.png

13c6398914c93eca8451caeae0da8158.png

  朕已阅 d61972bfe6e6bf9806d0968998364fc0.gif

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家小花儿/article/detail/260680
推荐阅读
相关标签
  

闽ICP备14008679号