Spring之@Value注解


@Value 注解可以用來將外部的值動態注入到 Bean 中,在 @Value 注解中,可以使用 ${} 或 #{}。${} 與 #{} 的區別如下:

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

(2)@Value("#{}"):表示 SpEl 表達式通常用來獲取 bean 的屬性,或者調用 bean 的某個方法。

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

一、注入普通字符串

屬性文件內容如下:

str1=hello world

Java代碼如下:

// 直接將字符串賦值給 str 屬性
@Value("hello world")
private String str;
 
// 從屬性文件中獲取值
@Value("${str1}")
private String str1; // 結果:hello world

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

@Value("${str2:defaultValue}")
private String str2; // 結果:defaultValue

二、注入操作系統屬性

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

@Value("${systemProperties['os.name']}")
private String osName;

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

@Value("#{systemProperties['os.name']}")
private String osName; // 結果:Windows 10

三、注入表達式結果

在 @Value 中,允許我們使用表達式,然后自動計算表達式的結果。將結果復制給指定的變量。如下:

// 生成一個隨機數
@Value("#{ T(java.lang.Math).random() * 1000.0 }")
private double randomNumber;
 
// 使用 System 類獲取系統環境變量 PATH
@Value("#{ T(java.lang.System).getenv('path') }")
private String path;

四、注入其他Bean屬性

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

// 其他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 時,如果沒有指定名稱,則默認為類名首字母小寫,如:otherBean 。當然我們也可以使用 @Component("myName") 形式,指定其他 bean 的名稱,此時,訪問則需要使用 @Value("#{myName.name}")。如下:

// 其他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 注解中,也可以用來注入資源(Resource),如:文件資源、URL網絡資源等。如下:

// 注入文件資源
@Value("classpath:props/application.properties")
private Resource fileResource;
 
// 注入URL資源
@Value("https://www.hxstrive.com")
private Resource urlResource;

完整代碼如下:

@Service
public class ValueDemo5 {
 
    // 注入文件資源
    @Value("classpath:props/application.properties")
    private Resource fileResource;
 
    // 注入URL資源
    @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);
 
        // 輸出文件資源內容
        String fileContent = FileUtils.readFileToString(
                demo.getFileResource().getFile(), "UTF-8");
        System.out.println(fileContent);
 
        // 輸出URL資源內容
        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是使用在非靜態方法上的,對於靜態方法,以下做法是無效的:

@Value("${myProp}")
public static String myProp;

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

private static String str1;
 
@Value("${str1}")
public void setStr1(String str1) {
    System.out.println("setStr1 ===> " + str1);
    ValueDemo7.str1 = str1;
}

如果將 setStr1() 方法設置成 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) 

七、引用外部屬性文件

通過 @Value 將外部配置文件的值動態注入到Bean中。配置文件主要有兩類:

application.properties

在 spring boot 啟動時默認加載此文件 application.properties,spring 則需要我們配置:

<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
    <!-- 設置如果沒有找到匹配的系統屬性,是否搜索匹配的系統環境變量 -->
    <property name="searchSystemEnvironment" value="true" />
    <!-- 設置如何檢查系統屬性(SYSTEM_PROPERTIES_MODE_FALLBACK=1) -->
    <property name="systemPropertiesMode" value="1"/>
    <!-- 加載屬性文件,指定屬性文件地址,可以指定多個 -->
    <property name="locations">
        <list>
            <value>classpath:props/application.properties</value>
        </list>
    </property>
</bean>

自定義屬性文件

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

# config.properties 文件
env.model=dev
 
# config_dev.properties 文件
name=
 
# config_prod.properties 文件
name=
 
# config_test.properties 文件
name=

java 代碼如下:

// 引入多個屬性配置文件
@Component
@PropertySource({
    "classpath:config.properties",
    "classpath:config_${env.model}.properties"
})
public class MyBean {
 
}

本文轉載自:https://www.hxstrive.com/article/854.htm


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM