日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

@Value,@ConfigurationProperties,@EnableConfigurationProperties,@PropertySource,@PropertySources

發(fā)布時(shí)間:2023/12/20 编程问答 38 豆豆
生活随笔 收集整理的這篇文章主要介紹了 @Value,@ConfigurationProperties,@EnableConfigurationProperties,@PropertySource,@PropertySources 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

@Value 注解可以用來(lái)將外部的值動(dòng)態(tài)注入到 Bean 中,在 @Value 注解中,可以使用 ${} 或 #{}。${} 與 #{} 的區(qū)別如下:

(1)@Value("${}"):可以獲取對(duì)應(yīng)屬性文件中定義的屬性值。

(2)@Value("#{}"):表示 SpEl 表達(dá)式通常用來(lái)獲取 bean 的屬性,或者調(diào)用 bean 的某個(gè)方法。

@Value 注解的常用使用方式如下:

注入普通字符串

屬性文件內(nèi)容如下:

1

str1=hello?world

Java代碼如下:

1

2

3

4

5

6

7

//?直接將字符串賦值給?str?屬性

@Value("hello?world")

private?String?str;

//?從屬性文件中獲取值

@Value("${str1}")

private?String?str1;?//?結(jié)果:hello?world

如果在屬性文件中沒(méi)有定義 str1 屬性名,則 @Value 會(huì)拋出如下錯(cuò)誤“java.lang.IllegalArgumentException: Could not resolve placeholder 'str1' in value "${str1}"”。我們可以在 str1 屬性不存在時(shí),指定默認(rèn)值,即使沒(méi)有定義 str2 也不會(huì)拋出錯(cuò)誤,而是返回默認(rèn)值。如下:

1

2

@Value("${str2:defaultValue}")

private?String?str2;?//?結(jié)果:defaultValue

注入操作系統(tǒng)屬性

可以利用 @Value 注入操作系統(tǒng)屬性。這里我們不能使用“${}”去獲取操作系統(tǒng)屬性。如下:

1

2

@Value("${systemProperties['os.name']}")

private?String?osName;

上面代碼將拋出 java.lang.IllegalArgumentException: Could not resolve placeholder 'systemProperties['os.name']' in value "${systemProperties['os.name']}" 錯(cuò)誤信息。你需要將 ${} 改為 #{},如下:

1

2

@Value("#{systemProperties['os.name']}")

private?String?osName;?//?結(jié)果:Windows?10

注入表達(dá)式結(jié)果

在 @Value 中,允許我們使用表達(dá)式,然后自動(dòng)計(jì)算表達(dá)式的結(jié)果。將結(jié)果復(fù)制給指定的變量。如下:

1

2

3

4

5

6

7

//?生成一個(gè)隨機(jī)數(shù)

@Value("#{?T(java.lang.Math).random()?*?1000.0?}")

private?double?randomNumber;

//?使用?System?類獲取系統(tǒng)環(huán)境變量?PATH

@Value("#{?T(java.lang.System).getenv('path')?}")

private?String?path;

注入其他Bean屬性

在 @Value 注解中,也可以將其他 bean 的屬性值注入到當(dāng)前 bean。如下:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

//?其他Bean

@Component

public?class?OtherBean?{

????@Value("OtherBean的NAME屬性")

????private?String?name;

????public?String?getName()?{

????????return?name;

????}

????public?void?setName(String?name)?{

????????this.name?=?name;

????}

}

//?用法

@Component

public?class?MyBean?{

????@Value("#{otherBean.name}")

????private?String?fromAnotherBean;

????//?...

}

注意,其他 bean 使用?@Component 時(shí),如果沒(méi)有指定名稱,則默認(rèn)為類名首字母小寫(xiě),如:otherBean 。當(dāng)然我們也可以使用?@Component("myName") 形式,指定其他 bean 的名稱,此時(shí),訪問(wèn)則需要使用 @Value("#{myName.name}")。如下:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

//?其他bean,自定義名稱為?myBeans

@Component("myBeans")

public?class?OtherBean2?{

????@Value("OtherBean的NAME屬性")

????private?String?name;

????public?String?getName()?{

????????return?name;

????}

????public?void?setName(String?name)?{

????????this.name?=?name;

????}

}

//?用法

@Component

public?class?MyBean?{

????@Value("#{myBeans.name}")

????private?String?fromAnotherBean2;

????//?...

}

注入資源

在 @Value 注解中,也可以用來(lái)注入資源(Resource),如:文件資源、URL網(wǎng)絡(luò)資源等。如下:

1

2

3

4

5

6

7

//?注入文件資源

@Value("classpath:props/application.properties")

private?Resource?fileResource;

//?注入U(xiǎn)RL資源

@Value("https://www.hxstrive.com")

private?Resource?urlResource;

完整代碼如下:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

@Service

public?class?ValueDemo5?{

????//?注入文件資源

????@Value("classpath:props/application.properties")

????private?Resource?fileResource;

????//?注入U(xiǎn)RL資源

????@Value("https://www.hxstrive.com")

????private?Resource?urlResource;

????public?static?void?main(String[]?args)?throws?Exception?{

????????ApplicationContext?context?=?new?ClassPathXmlApplicationContext(

????????????????"applicationContent-value.xml");

????????ValueDemo5?demo?=?context.getBean(ValueDemo5.class);

????????//?輸出文件資源內(nèi)容

????????String?fileContent?=?FileUtils.readFileToString(

????????????????demo.getFileResource().getFile(),?"UTF-8");

????????System.out.println(fileContent);

????????//?輸出URL資源內(nèi)容

????????ByteArrayOutputStream?outputStream?=?new?ByteArrayOutputStream();

????????BufferedInputStream?inputStream?=?new?BufferedInputStream(

????????????????demo.getUrlResource().getInputStream());

????????byte[]?buffer?=?new?byte[2048];

????????int?len;

????????while((len?=?inputStream.read(buffer))?!=?-1)?{

????????????outputStream.write(buffer,?0,?len);

????????}

????????System.out.println(new?String(outputStream.toByteArray(),?"UTF-8"));

????}

????public?Resource?getFileResource()?{

????????return?fileResource;

????}

????public?void?setFileResource(Resource?fileResource)?{

????????this.fileResource?=?fileResource;

????}

????public?Resource?getUrlResource()?{

????????return?urlResource;

????}

????public?void?setUrlResource(Resource?urlResource)?{

????????this.urlResource?=?urlResource;

????}

}

@Value注入static屬性

一般@Value是使用在非靜態(tài)方法上的,對(duì)于靜態(tài)方法,以下做法是無(wú)效的:

1

2

@Value("${myProp}")

public?static?String?myProp;

如果要向靜態(tài)屬性注入值,可以使用set方法注入,如下:

1

2

3

4

5

6

7

private?static?String?str1;

@Value("${str1}")

public?void?setStr1(String?str1)?{

????System.out.println("setStr1?===>?"?+?str1);

????ValueDemo7.str1?=?str1;

}

如果將 setStr1() 方法設(shè)置成 static,則 Spring 將拋出如下告警信息:

13:26:34 WARN [org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor] - Autowired annotation is not supported on static methods: public static void com.huangx.spring4.value.ValueDemo7.setStr1(java.lang.String)

引用外部屬性文件

通過(guò) @Value 將外部配置文件的值動(dòng)態(tài)注入到Bean中。配置文件主要有兩類:

application.properties

在 spring boot 啟動(dòng)時(shí)默認(rèn)加載此文件 application.properties,spring 則需要我們配置:

1

2

3

4

5

6

7

8

9

10

11

12

<bean?class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">

????<!--?設(shè)置如果沒(méi)有找到匹配的系統(tǒng)屬性,是否搜索匹配的系統(tǒng)環(huán)境變量?-->

????<property?name="searchSystemEnvironment"?value="true"?/>

????<!--?設(shè)置如何檢查系統(tǒng)屬性(SYSTEM_PROPERTIES_MODE_FALLBACK=1)?-->

????<property?name="systemPropertiesMode"?value="1"/>

????<!--?加載屬性文件,指定屬性文件地址,可以指定多個(gè)?-->

????<property?name="locations">

????????<list>

????????????<value>classpath:props/application.properties</value>

????????</list>

????</property>

</bean>

自定義屬性文件

自定義屬性文件通過(guò) @PropertySource 加載,@PropertySource 可以同時(shí)加載多個(gè)文件,也可以加載單個(gè)文件。如果第一個(gè)屬性文件和第二屬性文件存在相同key,則最后一個(gè)屬性文件里的key起作用(前面屬性文件的key將被覆蓋)。加載文件的路徑也可以配置變量,如下面實(shí)例中 config.properties 屬性文件的 ${env.model}(用來(lái)指定開(kāi)發(fā)環(huán)境模式,如:dev-開(kāi)發(fā)環(huán)境、prod-生產(chǎn)環(huán)境、test-測(cè)試環(huán)境)

@ConfigurationProperties#

Spring源碼中大量使用了ConfigurationProperties注解,比如server.port就是由該注解獲取到的,通過(guò)與其他注解配合使用,能夠?qū)崿F(xiàn)Bean的按需配置。

該注解有一個(gè)prefix屬性,通過(guò)指定的前綴,綁定配置文件中的配置,該注解可以放在類上,也可以放在方法上

可以從注解說(shuō)明中看到,當(dāng)將該注解作用于方法上時(shí),如果想要有效的綁定配置,那么該方法需要有@Bean注解且所屬Class需要有@Configuration注解。

簡(jiǎn)單一句話概括就是:Sring的有效運(yùn)行是通過(guò)上下文(Bean容器)中Bean的配合完成的,Bean可以簡(jiǎn)單理解成對(duì)象,有些對(duì)象需要指定字段內(nèi)容,那么這些內(nèi)容我們可以通過(guò)配置文件進(jìn)行綁定,然后將此Bean歸還給容器

作用于方法#

比較常見(jiàn)的就是配置讀寫(xiě)分離的場(chǎng)景。

配置文件內(nèi)容#

spring.datasource.druid.write.url=jdbc:mysql://localhost:3306/jpa spring.datasource.druid.write.username=root spring.datasource.druid.write.password=1 spring.datasource.druid.write.driver-class-name=com.mysql.jdbc.Driverspring.datasource.druid.read.url=jdbc:mysql://localhost:3306/jpa spring.datasource.druid.read.username=root spring.datasource.druid.read.password=1 spring.datasource.druid.read.driver-class-name=com.mysql.jdbc.Driver

@Configuration public class DruidDataSourceConfig {/*** DataSource 配置* @return*/@ConfigurationProperties(prefix = "spring.datasource.druid.read")@Bean(name = "readDruidDataSource")public DataSource readDruidDataSource() {return new DruidDataSource();}/*** DataSource 配置* @return*/@ConfigurationProperties(prefix = "spring.datasource.druid.write")@Bean(name = "writeDruidDataSource")@Primarypublic DataSource writeDruidDataSource() {return new DruidDataSource();} }

也許有的人看到這里會(huì)比較疑惑,prefix并沒(méi)有指定配置的全限定名,那它是怎么進(jìn)行配置綁定的呢?

相信大家肯定了解@Value注解,它可以通過(guò)全限定名進(jìn)行配置的綁定,這里的ConfigurationProperties其實(shí)就類似于使用多個(gè)@Value同時(shí)綁定,綁定的對(duì)象就是DataSource類型的對(duì)象,而且是?隱式綁定?的,意味著在配置文件編寫(xiě)的時(shí)候需要與對(duì)應(yīng)類的字段名稱?相同,比如上述spring.datasource.druid.write.url=jdbc:mysql://localhost:3306/jpa?,當(dāng)然了,你也可以隨便寫(xiě)個(gè)配置,比如?spring.datasource.druid.write.uuu=www.baidu.com,此時(shí)你只需要在注解中加上以下參數(shù)即可

以上就完成了多個(gè)數(shù)據(jù)源的配置,為讀寫(xiě)分離做了鋪墊

作用于Class類及其用法#

配置文件內(nèi)容#

spring.datasource.url=jdbc:mysql://127.0.0.1:8888/test?useUnicode=false&autoReconnect=true&characterEncoding=utf-8 spring.datasource.username=root spring.datasource.password=root spring.datasource.driver-class-name=com.mysql.jdbc.Driver spring.datasource.type=com.alibaba.druid.pool.DruidDataSource @ConfigurationProperties(prefix = "spring.datasource") @Component public class DatasourcePro {private String url;private String username;private String password;// 配置文件中是driver-class-name, 轉(zhuǎn)駝峰命名便可以綁定成private String driverClassName;private String type;public String getUrl() {return url;}public void setUrl(String url) {this.url = url;}public String getUsername() {return username;}public void setUsername(String username) {this.username = username;}public String getPassword() {return password;}public void setPassword(String password) {this.password = password;}public String getDriverClassName() {return driverClassName;}public void setDriverClassName(String driverClassName) {this.driverClassName = driverClassName;}public String getType() {return type;}public void setType(String type) {this.type = type;} } @Controller @RequestMapping(value = "/config") public class ConfigurationPropertiesController {@Autowiredprivate DatasourcePro datasourcePro;@RequestMapping("/test")@ResponseBodypublic Map<String, Object> test(){Map<String, Object> map = new HashMap<>();map.put("url", datasourcePro.getUrl());map.put("userName", datasourcePro.getUsername());map.put("password", datasourcePro.getPassword());map.put("className", datasourcePro.getDriverClassName());map.put("type", datasourcePro.getType());return map;} }

  • @ConfigurationProperties 和 @value 有著相同的功能,但是 @ConfigurationProperties的寫(xiě)法更為方便
  • @ConfigurationProperties 的 POJO類的命名比較嚴(yán)格,因?yàn)樗仨毢蚿refix的后綴名要一致, 不然值會(huì)綁定不上, 特殊的后綴名是“driver-class-name”這種帶橫杠的情況,在POJO里面的命名規(guī)則是?下劃線轉(zhuǎn)駝峰?就可以綁定成功,所以就是 “driverClassName”
  • @EnableConfigurationProperties

    先說(shuō)作用:

    @EnableConfigurationProperties注解的作用是:使使用 @ConfigurationProperties 注解的類生效。

    說(shuō)明:

    如果一個(gè)配置類只配置@ConfigurationProperties注解,而沒(méi)有使用@Component,那么在IOC容器中是獲取不到properties 配置文件轉(zhuǎn)化的bean。說(shuō)白了 @EnableConfigurationProperties 相當(dāng)于把使用 @ConfigurationProperties 的類進(jìn)行了一次注入。
    測(cè)試發(fā)現(xiàn) @ConfigurationProperties 與 @EnableConfigurationProperties 關(guān)系特別大。

    測(cè)試證明:
    @ConfigurationProperties 與 @EnableConfigurationProperties 的關(guān)系。

    @EnableConfigurationProperties 文檔中解釋:
    當(dāng)@EnableConfigurationProperties注解應(yīng)用到你的@Configuration時(shí), 任何被@ConfigurationProperties注解的beans將自動(dòng)被Environment屬性配置。 這種風(fēng)格的配置特別適合與SpringApplication的外部YAML配置進(jìn)行配合使用。

    測(cè)試發(fā)現(xiàn):
    1.使用 @EnableConfigurationProperties 進(jìn)行注冊(cè)

    @ConfigurationProperties(prefix = "service.properties") public class HelloServiceProperties {private static final String SERVICE_NAME = "test-service";private String msg = SERVICE_NAME;set/get }@Configuration @EnableConfigurationProperties(HelloServiceProperties.class) @ConditionalOnClass(HelloService.class) @ConditionalOnProperty(prefix = "hello", value = "enable", matchIfMissing = true) public class HelloServiceAutoConfiguration {}@RestController public class ConfigurationPropertiesController {@Autowiredprivate HelloServiceProperties helloServiceProperties;@RequestMapping("/getObjectProperties")public Object getObjectProperties () {System.out.println(helloServiceProperties.getMsg());return myConfigTest.getProperties();} }

    自動(dòng)配置設(shè)置

    service.properties.name=my-test-name service.properties.ip=192.168.1.1 service.user=kayle service.port=8080

    一切正常,但是 HelloServiceAutoConfiguration 頭部不使用 @EnableConfigurationProperties,測(cè)訪問(wèn)報(bào)錯(cuò)。

    2.不使用 @EnableConfigurationProperties 進(jìn)行注冊(cè),使用 @Component 注冊(cè)

    @ConfigurationProperties(prefix = "service.properties") @Component public class HelloServiceProperties {private static final String SERVICE_NAME = "test-service";private String msg = SERVICE_NAME;public String getMsg() {return msg;}public void setMsg(String msg) {this.msg = msg;}}

    Controller 不變,一切正常,如果注釋掉 @Component 測(cè)啟動(dòng)報(bào)錯(cuò)。
    由此證明,兩種方式都是將被 @ConfigurationProperties 修飾的類,加載到 Spring Env 中。

    簡(jiǎn)單介紹一下@PropertySource和@PropertySources這倆注解
    @PropertySource注解概述
    @PropertySource注解是Spring 3.1開(kāi)始引入的配置類注解。通過(guò)@PropertySource注解可以將properties配置文件中的key/value存儲(chǔ)到Spring的Environment中,Environment接口提供了方法去讀取配置文件中的值,參數(shù)是properties配置文件中定義的key值。當(dāng)然了,也可以使用@Value注解用${}占位符為bean的屬性注入值。

    我們來(lái)看一下@PropertySource注解的源代碼,如下所示。

    從@PropertySource的源碼中可以看出,我們可以通過(guò)@PropertySource注解指定多個(gè)properties文件,使用的形式如下所示。

    @PropertySource(value={"classpath:/person.properties", "classpath:/car.properties"})
    1
    細(xì)心的讀者可以看到,在@PropertySource注解的上面標(biāo)注了如下的注解信息。

    @Repeatable(PropertySources.class)
    1
    看到這里,小伙伴們是不是有種恍然大悟的感覺(jué)呢?沒(méi)錯(cuò),我們也可以使用@PropertySources注解來(lái)指定properties配置文件。

    @PropertySources注解概述
    首先,我們也來(lái)看下@PropertySources注解的源碼,如下所示。

    @PropertySources注解的源碼比較簡(jiǎn)單,只有一個(gè)PropertySource[]數(shù)組類型的value屬性,那我們?nèi)绾问褂?#64;PropertySources注解指定配置文件呢?其實(shí)也很簡(jiǎn)單,使用如下所示的方式就可以了。

    @PropertySources(value={
    ? ? @PropertySource(value={"classpath:/person.properties"}),
    ? ? @PropertySource(value={"classpath:/car.properties"}),
    })

    是不是很簡(jiǎn)單呢?接下來(lái),我們就以一個(gè)小案例來(lái)說(shuō)明@PropertySource注解的用法。

    一個(gè)小案例來(lái)說(shuō)明@PropertySource注解的用法
    準(zhǔn)備工作
    首先,我們?cè)诠こ痰膕rc/main/resources目錄下創(chuàng)建一個(gè)配置文件,例如person.properties,該文件的內(nèi)容如下所示。

    person.nickName=小甜甜
    1
    然后,我們?cè)赑erson類中新增一個(gè)nickName字段,如下所示。

    package com.meimeixia.bean;import org.springframework.beans.factory.annotation.Value;public class Person {@Value("李阿昀")private String name;@Value("#{20-2}")private Integer age;private String nickName; // 昵稱public String getNickName() {return nickName;}public void setNickName(String nickName) {this.nickName = nickName;}public String getName() {return name;}public void setName(String name) {this.name = name;}public Integer getAge() {return age;}public void setAge(Integer age) {this.age = age;}public Person(String name, Integer age) {super();this.name = name;this.age = age;}public Person() {super();// TODO Auto-generated constructor stub}@Overridepublic String toString() {return "Person [name=" + name + ", age=" + age + ", nickName=" + nickName + "]";}}

    ?

    目前,我們并沒(méi)有為Person類的nickName字段賦值,所以,此時(shí)Person類的nickName字段的值為空。我們可以運(yùn)行IOCTest_PropertyValue類中的test01()方法來(lái)看下輸出結(jié)果,如下所示。

    可以看到,Person類的nickName字段的值確實(shí)輸出了null。

    使用注解方式獲取值

    如果我們使用注解的方式,那么該如何做呢?首先,我們需要在MainConfigOfPropertyValues配置類上添加一個(gè)@PropertySource注解,如下所示。

    ?

    package com.meimeixia.config;import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.PropertySource;import com.meimeixia.bean.Person;// 使用@PropertySource讀取外部配置文件中的key/value保存到運(yùn)行的環(huán)境變量中,加載完外部的配置文件以后,使用${}取出配置文件中的值 @PropertySource(value={"classpath:/person.properties"}) @Configuration public class MainConfigOfPropertyValues {@Beanpublic Person person() {return new Person();}}

    ?

    這里使用的@PropertySource(value={"classpath:/person.properties"})注解就相當(dāng)于XML配置文件中使用的<context:property-placeholder location="classpath:person.properties" />。

    然后,我們就可以在Person類的nickName字段上使用@Value注解來(lái)獲取person.properties文件中的值了,如下所示。

    @Value("${person.nickName}")
    private String nickName; // 昵稱

    配置完成后,我們?cè)俅芜\(yùn)行IOCTest_PropertyValue類中的test01()方法來(lái)看下輸出結(jié)果,如下所示。
    可以看到,此時(shí)Person類的nickName字段已經(jīng)注入小甜甜這個(gè)值了。

    使用Environment獲取值
    上面我已經(jīng)說(shuō)過(guò),使用@PropertySource注解讀取外部配置文件中的key/value之后,是將其保存到運(yùn)行的環(huán)境變量中了,所以我們也可以通過(guò)運(yùn)行環(huán)境來(lái)獲取外部配置文件中的值。

    這里,我們可以稍微修改一下IOCTest_PropertyValue類中的test01()方法,即在其中添加一段使用Environment獲取person.properties文件中的值的代碼,如下所示。

    @Test public void test01() {printBeans(applicationContext);System.out.println("===================");Person person = (Person) applicationContext.getBean("person");System.out.println(person);ConfigurableEnvironment environment = applicationContext.getEnvironment();String property = environment.getProperty("person.nickName");System.out.println(property);// 關(guān)閉容器applicationContext.close(); }

    ?運(yùn)行以上test01()方法,可以看到輸出的結(jié)果信息如下所示。

    可以看到,使用Environment確實(shí)能夠獲取到person.properties文件中的值。

    ?

    總結(jié)

    以上是生活随笔為你收集整理的@Value,@ConfigurationProperties,@EnableConfigurationProperties,@PropertySource,@PropertySources的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

    如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。