天天看點

@value注解取不到值_【Spring注解驅動開發】使用@PropertySource加載配置檔案,我隻看這一篇!!

@value注解取不到值_【Spring注解驅動開發】使用@PropertySource加載配置檔案,我隻看這一篇!!

寫在前面

很多小夥伴都在問:冰河,你的Spring專題更新完了嗎?怎麼感覺像是寫了一半啊?我:沒有更新完呀,整個專題預計會有70多篇。那怎麼更新了一半就去寫别的了呢?那是因為有很多其他的小夥伴在背景留言說:急需學習一些其他的技術,是以,臨時調整的。放心,Spring專題會持續更新的!這不,今天,我們就繼續更新Spring專題。不出意外的話,會一直持續更新完!!

關注 冰河技術 微信公衆号,背景回複“Spring注解”關鍵字擷取源碼。

@PropertySource注解概述

@PropertySource注解是Spring 3.1開始引入的配置類注解。通過@PropertySource注解将properties配置檔案中的值存儲到Spring的 Environment中,Environment接口提供方法去讀取配置檔案中的值,參數是properties檔案中定義的key值。也可以使用@Value 注解用${}占位符注入屬性。

@PropertySource注解的源代碼如下所示。

package org.springframework.context.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Repeatable;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.core.io.support.PropertySourceFactory;

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Repeatable(PropertySources.class)
public @interface PropertySource {
 String name() default "";
 String[] value();
 boolean ignoreResourceNotFound() default false;
 String encoding() default "";
 Class<? extends PropertySourceFactory> factory() default PropertySourceFactory.class;
}

           

從@PropertySource的源碼可以看出,我們可以通過@PropertySource注解指定多個properties檔案,可以使用如下形式進行指定。

@PropertySource(value={"classpath:xxx.properties", "classpath:yyy.properties"})
           

細心的讀者可以看到,在@PropertySource注解類的上面标注了如下的注解資訊。

@Repeatable(PropertySources.class)
           

看到這裡,小夥伴們是不是有種恍然大悟的感覺呢?沒錯,我們也可以使用@PropertySources注解來指定properties配置檔案。

@PropertySources注解

首先,我們也是看下@PropertySources注解的源碼,如下所示。

package org.springframework.context.annotation;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface PropertySources {
 PropertySource[] value();
}
           

@PropertySources注解的源碼比較簡單,隻有一個PropertySource[]數組類型的屬性value,那我們如何使用@PropertySources注解指定配置檔案呢?其實也很簡單,就是使用如下所示的方式就可以了。

@PropertySources(value={
    @PropertySource(value={"classpath:xxx.properties"}),
    @PropertySource(value={"classpath:yyy.properties"}),
})
           

是不是很簡單呢?接下來,我們就以一個小案例來說明@PropertySource注解的用法。

案例準備

首先,我們在工程的src/main/resources目錄下建立一個配置檔案person.properties檔案,檔案的内容如下所示。

person.nickName=zhangsan
           

接下來,我們在Person類中新增一個字段nickName,如下所示。

package io.mykit.spring.plugins.register.bean;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;
import org.springframework.beans.factory.annotation.Value;
import java.io.Serializable;

/**
 * @author binghe
 * @version 1.0.0
 * @description 測試實體類
 */
@Data
@ToString
@NoArgsConstructor
@AllArgsConstructor
public class Person implements Serializable {
    private static final long serialVersionUID = 7387479910468805194L;
    @Value("binghe")
    private String name;
    @Value("#{20-2}")
    private Integer age;
    private String nickName;
}
           

目前,我們并沒有為Person類的nickName字段指派,是以,此時Person類的nickName字段的值為空。我們運作下PropertyValueTest類的testPropertyValue01()方法來看下輸出結果,如下所示。

org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
propertyValueConfig
person
================================
Person(name=binghe, age=18, nickName=null)
Process finished with exit code 0
           

可以看出,Person類的nickName字段的值确實輸出了null。

使用xml檔案方式擷取值

如果我們需要在xml檔案中擷取person.properties檔案中的值,則我們首先需要在Spring的xml檔案中引入context名稱空間,并且使用context命名空間導入person.properties檔案,之後在bean的屬性字段中使用如下方式将person.properties檔案中的值注入到Person類的nickName字段上。

<context:property-placeholder location="classpath:person.properties" />
<bean id = "person" class="io.mykit.spring.plugins.register.bean.Person">
    <property name="name" value="binghe"></property>
    <property name="age" value="18"></property>
    <property name="nickName" value="${person.nickName}"></property>
</bean>
           

整個bean.xml檔案的内容如下所示。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
                           http://www.springframework.org/schema/beans/spring-beans.xsd
                           http://www.springframework.org/schema/context
                           http://www.springframework.org/context/spring-context.xsd ">
    
    <context:property-placeholder location="classpath:person.properties"/>
    <bean id = "person" class="io.mykit.spring.plugins.register.bean.Person">
        <property name="name" value="binghe"></property>
        <property name="age" value="18"></property>
        <property name="nickName" value="${person.nickName}"></property>
    </bean>
</beans>
           

這樣就可以将person.properties檔案中的值注入到Person的nickName字段上。接下來,我們在PropertyValueTest類中建立testPropertyValue02()測試方法,如下所示。

@Test
public void testPropertyValue02(){
    ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("classpath:beans.xml");
    Person person = (Person) context.getBean("person");
    System.out.println(person);
}
           

我們運作PropertyValueTest類中建立的testPropertyValue02()方法,輸出的結果資訊如下所示。

Person(name=binghe, age=18, nickName=zhangsan)
           

使用注解方式擷取值

如果我們使用注解的方式該如何做呢?首先,我們需要在PropertyValueConfig配置類上添加@PropertySource注解,如下所示。

package io.mykit.spring.plugins.register.config;
import io.mykit.spring.plugins.register.bean.Person;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
/**
 * @author binghe
 * @version 1.0.0
 * @description 測試屬性指派
 */
@PropertySource(value = {"classpath:person.properties"})
@Configuration
public class PropertyValueConfig {
    @Bean
    public Person person(){
        return new Person();
    }
}
           

這裡使用的

@PropertySource(value = {"classpath:person.properties"})

就相當于xml檔案中使用的

<context:property-placeholder location="classpath:person.properties"/>

接下來,我們就可以在Person類的nickName字段上使用@Value注解來擷取person.properties檔案中的值了,如下所示。

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

配置完成後,我們再次運作PropertyValueTest類的testPropertyValue01()方法來看下輸出結果,如下所示。

org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
propertyValueConfig
person
================================
Person(name=binghe, age=18, nickName=zhangsan)
           

可以看到,此時Person類的nickName字段已經注入了“zhangsan”這個值。

使用Environment擷取值

這裡,我們在PropertyValueTest類中建立testPropertyValue03()方法,來使用Environment擷取person.properties中的值,如下所示。

@Test
public void testPropertyValue03(){
    AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(PropertyValueConfig.class);
    Environment environment = context.getEnvironment();
    String nickName = environment.getProperty("person.nickName");
    System.out.println(nickName);
}
           

運作PropertyValueTest類中的testPropertyValue03()方法,輸出的結果資訊如下所示。

zhangsan
           

可以看到,使用Environment确實能夠擷取到person.properties中的值。

重磅福利

關注「

冰河技術

」微信公衆号,背景回複 “

設計模式

” 關鍵字領取《

深入淺出Java 23種設計模式

》PDF文檔。回複“

Java8

”關鍵字領取《

Java8新特性教程

》PDF文檔。回複“

限流

”關鍵字擷取《

億級流量下的分布式限流解決方案

》PDF文檔,三本PDF均是由冰河原創并整理的超硬核教程,面試必備!!

好了,今天就聊到這兒吧!别忘了點個贊,給個在看和轉發,讓更多的人看到,一起學習,一起進步!!

寫在最後

如果你覺得冰河寫的還不錯,請微信搜尋并關注「 冰河技術 」微信公衆号,跟冰河學習高并發、分布式、微服務、大資料、網際網路和雲原生技術,「 冰河技術 」微信公衆号更新了大量技術專題,每一篇技術文章幹貨滿滿!不少讀者已經通過閱讀「 冰河技術 」微信公衆号文章,吊打面試官,成功跳槽到大廠;也有不少讀者實作了技術上的飛躍,成為公司的技術骨幹!如果你也想像他們一樣提升自己的能力,實作技術能力的飛躍,進大廠,升職加薪,那就關注「 冰河技術 」微信公衆号吧,每天更新超硬核技術幹貨,讓你對如何提升技術能力不再迷茫!

http://weixin.qq.com/r/dB10bAHE0FyvrUUP90hm (二維碼自動識别)

繼續閱讀