Featured image of post 論@Value與Environment之優劣

論@Value與Environment之優劣

SpringBoot裡面,想從Application.properties中取值有兩種方式,哪種比較好呢?

SpringBoot中想要從Application.properties中取的值,有兩種常見的方式,其中一種是利用@Value的方式

@Value

1
2
@Value("${app.version})
String version

Enviroment

另一種則是透過 Enviroment物件來取的

1
2
3
4
5
private final Environment env;

public String getAppVersion() {
        return environment.getProperty("app.version");
    }

以取值的表現形式來看

在某些情形下,我們可能會從applicaiton.properties中取出一個陣列值,比如說

1
language=en,zh,jp

這時如果使用Enviroment來取,取出來的值會一個String,需要再透過轉換,將它變為一個String

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
@Autowired
private Environment env;

public String[] getMyArrayProperty() {
    String propertyValue = env.getProperty("my.array.property");
    if (propertyValue != null) {
        return propertyValue.split(",");
    } else {
        return new String[0];
    }
}

但如果用@Value的方式來取值,則可以在宣告變數時,聲明它是一個String或是一個String[],避免後續的轉換

1
2
@Value("${language}")
private String[] myArray;

以單元測試角度來看

這兩個表現形式幾乎一模一樣,都可以取得想要的部分,但最大差別就在單元測試時,由於@Value這個取值方式有賴將整個SpringBoot專案啟動才可以注入,在單元測試的環境下並沒有辦法做到這件事情。但相反的,由於Environment本身屬於一個外部依賴,我們可以很好的替代掉他

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
@Service
public class VersionService {

    Environment environment;

    public VersionService(Environment environment) {
        this.environment = environment;
    }

    public String getEunoExAppVersion() {
        return environment.getProperty("eunoex.version");
    }
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
@ExtendWith(MockitoExtension.class)
class VersionServiceTest {
    @Mock
    Environment environment;
    @InjectMocks
    VersionService versionService;
    @Test
    void getAppVersion_everythingFine_returnSuccessfully() {
        given(environment.getProperty(any())).willReturn("v1.2.0");
        String ExAppVersion = versionService.getAppVersion();
        System.out.println("AppVersion = " + AppVersion);
    }

}

大概Guy4這樣