首页 > 解决方案 > Spring - 使用值注释从本地配置文件中读取

问题描述

我正在尝试使用 Spring 中的 Value 注释从本地 application.yaml 文件中读取,该文件与我的主测试类和单元测试类放在同一个包中。我有一个简单的类,它具有获取配置值的方法:

public class EmailValidator {

    String getConfigValue(configurationProvider1 configurationReader, String configName) {
        String value = null;
        ConfigurationProvider reader;
        try {
            reader = configurationReader.configurationProvider();
            value = reader.getProperty(configName, String.class);
            //the `reader` above is null when I run the test, so I get Null Pointer Exception on this line
            if (value == null) {
                LOGGER.warn("The configuration for " + configName + " cannot be found.");
            }
        } catch (Exception e){
            e.printStackTrace();
        }

        return value;
    }
} 

我有一个配置提供程序类,它设置配置读取器,以便我上面的类可以利用它来读取 application.yaml 文件:

@Configuration
@AllArgsConstructor(access = AccessLevel.PACKAGE)
@NoArgsConstructor
@ComponentScan
public class configurationProvider1 {

        @Value("${configFilesPath:./domain/application.properties}")//Not really sure if this is the right way of locating my configuration file
        @Getter
        private String filePath;

        @Bean
        public ConfigurationProvider configurationProvider() throws FileNotFoundException {
            if (!Paths.get(this.filePath).toFile().exists()) {
                throw new FileNotFoundException("Configuration file doesn't exist: " + this.filePath);
            }

            ConfigFilesProvider configFilesProvider =
                    () -> Collections.singletonList(Paths.get(filePath).toAbsolutePath());
            ConfigurationSource source = new FilesConfigurationSource(configFilesProvider);
            Environment environment = new ImmutableEnvironment(this.filePath);

            return new ConfigurationProviderBuilder()
                    .withConfigurationSource(source)
                    .withEnvironment(environment)
                    .build();
        }
    } 

如上所述,我不确定是否@Value("${configFilesPath:./domain/application.properties}")是定位我的本地 application.properties 文件的正确方法(这些类位于同一个包中,domain但配置文件不在资源文件夹中,因为这是一个服务层。所以它就在domain包装下面)。

当我尝试在第一堂课中测试我的 getConfigValue 方法时,我得到了 NPE(我假设它是因为我作为参数传递给 getConfigValue 方法的 configurationReader 为空):

@RunWith(SpringRunner.class)
@SpringBootTest
public class EmailValidatorTest {

    @MockBean
    private configurationProvider1 configurationReader = mock(configurationProvider1.class);

    @Autowired
    private DefaultEmailValidator validator;//maybe I should inject the dependency somewhere?

    @Test
    public void simple(){
        String a = validator.getConfigValue(configurationReader,"mail.subject.max.length");
        System.out.println(a);
    } 

我不确定我的班级此时是否真的从配置文件中读取配置值。任何帮助将不胜感激!

PS 代码更新了

标签: javaspringspring-bootconfigurationnullpointerexception

解决方案


@价值

Spring 的@Value 注解提供了一种方便的方式将属性值注入到组件中,而不是提供属性文件路径

@PropertySource对该文档使用@PropertySource

注释提供了一种方便的声明机制,用于将 PropertySource 添加到 Spring 的环境中。@Configuration与类一起使用

给定一个包含键/值对的文件 app.properties testbean.name=myTestBean,以下@Configuration类使用@PropertySource 为app.propertiesEnvironment 的一组 PropertySources 做出贡献。

例子

 @Configuration
 @PropertySource("classpath:/com/myco/app.properties")
 public class AppConfig {

 @Autowired
 Environment env;

 @Bean
 public TestBean testBean() {
     TestBean testBean = new TestBean();
     testBean.setName(env.getProperty("testbean.name"));
     return testBean;
   }
 }

24.7.4 YAML 缺点

无法使用@PropertySource注解加载 YAML 文件。因此,如果您需要以这种方式加载值,则需要使用属性文件。

来到测试用例,您不应该创建DefaultEmailValidator需要使用的新实例@SpringBootTest

@SpringBootTest 示例

@SpringBootTest我们需要引导整个容器时,可以使用注解。注释通过创建将在我们的测试中使用的 ApplicationContext 来工作。

RunWith(SpringRunner.class)

@RunWith(SpringRunner.class) 用于在 Spring Boot 测试功能和 JUnit 之间架起一座桥梁。每当我们在 JUnit 测试中使用任何 Spring Boot 测试功能时,都需要此注解。

@MockBean

这里另一个有趣的事情是@MockBean 的使用。它创建了一个 Mock

电子邮件验证器测试

 @RunWith(SpringRunner.class)
 @SpringBootTest
 public class EmailValidatorTest {

@MockBean
private configurationProvider1 configurationReader;

@Autowire
private DefaultEmailValidator validator

@Test
public void testGetConfigValue(){
    String a = validator.getConfigValue(configurationReader,"mail.subject.max.length");
    System.out.println(a);
} 

推荐阅读