###### tags: `SpringBoot` `@Value`
# A Quick Guide to Spring @Value
## 專案結構

## Setting Up the Properties File
src/main/resources/MyConfiguration.properties
```properties=
config.type.user.name=Robin
config.type.user.id=001
config.type.user.mail=robin@gmail.com
config.type.user.is.married=true
config.type.demo.default=assign config.type.demo.default value xxx
config.type.string.array=ABC,DEF,GHI
config.type.int.array=7,8,9
#Note that the values in the Map must be in single quotes
config.type.map={key1: '1', key2: '2', key3: '3'}
```
## Setting Up the Properties Java Class
```java=
@Configuration
@PropertySource(
value = "classpath:MyConfiguration.properties",
ignoreResourceNotFound = true,
encoding="UTF-8")
public class DemoReadProperties {
@Value("${config.type.user.name}")
private String configTypeUserName;
@Value("${config.type.user.id}")
private String configTypeUserId;
@Value("${config.type.user.mail}")
private String configTypeUserMail;
@Value("${config.type.user.is.married}")
private Boolean configTypeUserIsMarried;
@Value("${config.type.demo.default:this is a default value}")
private String configTypeDemoDefault;
@Value("${config.type.string.array:one,two,three}")
private String[] configTypeStringArrayWithDefaults;
@Value("${config.type.int.array:1,2,3}")
private int[] configTypeIntArrayWithDefaults;
@Value("#{systemProperties['os.name'] ?: 'my default system property value'}")
private String spelWithSystemPropertiesValue;
@Value("#{${config.type.map}}")
private Map<String, Integer> configTypeMap;
//Getter...Setter
}
```
## Usage Examples
### 1. Basic and mostly useless example(String, int, double float, boolean)
```java=
@Value("${config.type.user.name}")
private String configTypeUserName;
@Value("${config.type.user.is.married}")
private Boolean configTypeUserIsMarried;
```
### 2. Default values can be provided for properties that might not be defined
> 冒號後面接著default value
```java=
@Value("${config.type.demo.default:this is a default value}")
private String configTypeDemoDefault;
```
### 3. Array properties
```properties=
config.type.string.array=ABC,DEF,GHI
config.type.int.array=7,8,9
```
> Array的每個值使用逗號相隔, Spring會自動將值轉成定義的data type
```java=
@Value("${config.type.string.array}")
private String[] configTypeStringArrayWithDefaults;
@Value("${config.type.int.array:1,2,3}")
private int[] configTypeIntArrayWithDefaults;
```
### 4. Using @Value With Maps
```properties=
#Note that the values in the Map must be in single quotes
config.type.map={key1: '1', key2: '2', key3: '3'}
```
> Array的每個值使用逗號相隔, Spring會自動將值轉成定義的data type
```java=
@Value("#{${config.type.map}}")
private Map<String, Integer> configTypeMap;
```
## ApplicationRunner (main function)
```java=
package person.tsungfuxie.springreadpropertiesexercise;
import java.util.Arrays;
import java.util.Map.Entry;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import person.tsungfuxie.springreadpropertiesexercise.properties.DemoReadProperties;
@SpringBootApplication
public class SpringReadPropertiesExerciseApplication implements ApplicationRunner {
private static Logger logger = LoggerFactory.getLogger(SpringReadPropertiesExerciseApplication.class);
@Autowired
private DemoReadProperties demoReadProperties;
public static void main(String[] args) {
SpringApplication.run(SpringReadPropertiesExerciseApplication.class, args);
}
@Override
public void run(ApplicationArguments args) throws Exception {
// TODO Auto-generated method stub
logger.info("Hello world!");
logger.info("====================Read Configuration===================");
logger.info("user name = {}", demoReadProperties.getConfigTypeUserName());
logger.info("user id = {}", demoReadProperties.getConfigTypeUserId());
logger.info("user mail = {}", demoReadProperties.getConfigTypeUserMail());
logger.info("user is married = {}", demoReadProperties.getConfigTypeUserIsMarried() ? "結婚了" : "單身狗");
logger.info("ConfigTypeDemoDefault = {}", demoReadProperties.getConfigTypeDemoDefault());
logger.info("StringArrayWithDefaults(length = {}) = {}", demoReadProperties.getConfigTypeStringArrayWithDefaults().length, demoReadProperties.getConfigTypeStringArrayWithDefaults());
logger.info("IntArrayWithDefaults(length = {}) = {}", demoReadProperties.getConfigTypeIntArrayWithDefaults().length, demoReadProperties.getConfigTypeIntArrayWithDefaults());
logger.info("spelWithSystemPropertiesValue = {}", demoReadProperties.getSpelWithSystemPropertiesValue());
for (Entry<String, Integer> mapEntry : demoReadProperties.getConfigTypeMap().entrySet()) {
logger.info("Map<{}, {}>", mapEntry.getKey(), mapEntry.getValue());
}
}
// @Bean
// public CommandLineRunner commandLineRunner(ApplicationContext context) {
// return args -> {
// logger.info("Let's inspect the beans provided by Spring Boot:");
// String[] beanNames = context.getBeanDefinitionNames();
// Arrays.sort(beanNames);
// for (String beanName : beanNames) {
// logger.info(beanName);
// }
// };
// }
}
```
## 測試結果
## 測試專案程式
Git clone: [https://github.com/tsungfuxie/spring-read-properties-exercise.git](https://github.com/tsungfuxie/spring-read-properties-exercise.git)
## 參考資源
[Baeldung Quick Guide to Spring @Value](https://www.baeldung.com/spring-value-annotation)
## mike 的例子
### 思路 20210929 mike add
利用Value註解來讓properties的檔案可以注入Bean裡面,這樣的好處有兩個
1. 如此一來更改預設的Bean attribute時,可以**統一**於properties檔案裡更改
2. 配合application.properties可以去使用切換dev環境或是prod環境
### application.properties
```
spring.profiles.active=dev
```
### service-dev.properties
```
# spread sheet id
SpreadSheet.ID=1sP5BeCtcG4l0MnOfTaKxJKFzUTbkpwLqulxxiYaWrKw
```
### service properties
```java=
package com.example.value.properties;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
@Configuration
@PropertySource(value = "classpath:service-${spring.profiles.active}.properties", encoding="UTF-8")
public class ServiceProperties {
@Value("${SpreadSheet.ID}")
String MainSpreadSheetID;
public String getMainSpreadSheetID() {
return MainSpreadSheetID;
}
public void setMainSpreadSheetID(String mainSpreadSheetID) {
MainSpreadSheetID = mainSpreadSheetID;
}
}
```
> 仔細去觀察spring.profiles.active在這裡起到了微妙的作用
### runner
```java=
package com.example.value;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import com.example.value.properties.ServiceProperties;
@SpringBootApplication
public class GoogleAccountBudgetContractAnnualConsumptionStatisticsApplication implements ApplicationRunner{
private static Logger logger = LoggerFactory.getLogger(GoogleAccountBudgetContractAnnualConsumptionStatisticsApplication.class);
@Autowired //放在main前面
ServiceProperties servicePreperties;
public static void main(String[] args) {
SpringApplication.run(GoogleAccountBudgetContractAnnualConsumptionStatisticsApplication.class, args);
}
@Override //放在main後面
public void run(ApplicationArguments args) throws Exception {
// TODO Auto-generated method stub
logger.info("Hello world!");
String SpreadsheetID=servicePreperties.getMainSpreadSheetID();
System.out.println(SpreadsheetID);
}
}
```