###### tags: `SpringBoot` `@Value` # A Quick Guide to Spring @Value ## 專案結構 ![](https://i.imgur.com/5Sv4L8a.png) ## 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); } } ```