Spring Boot应用程序需要在@Configuration类中为使用@Value定义默认bean?

时间:2018-08-20 12:09:05

标签: java spring spring-boot

最近,我遇到了一个非常奇怪的情况。

请考虑一个简单的Spring Boot应用程序:

@SpringBootApplication
public class SampleApp implements WebMvcConfigurer {

    public static void main(String[] args) {
            SpringApplication.run(SampleApp.class, args);
    }
}

在此SampleApp内,我们有一个Configuration类,例如:

@Configuration
public class Config {

    //Some @Bean definitions, but without things such as String
}

然后我们有一些课程:

@Service
@RequiredArgsConstructor //Lombok
public class SomeService {

    @Value("${value.to.be.injected}")
    private final String someValue;
}

在当前状态下,应用程序拒绝启动:

***************************
APPLICATION FAILED TO START
***************************
Description:

Parameter 0 of constructor in com.sampleapp required a bean of type 'java.lang.String' that could not be found.

Action:

Consider defining a bean of type 'java.lang.String' in your configuration.

但是,我们应该在我们的配置中定义一个@Bean,例如:

@Configuration
public class Config {

    @Bean
    public String string() {
        return new String();
    }
}

应用程序可以正确启动,甚至可以正确地注入值。为什么会发生这种情况,为什么Spring会这样?

1 个答案:

答案 0 :(得分:2)

我的猜测是,您已在构造函数中添加了“ someValue”,它试图创建实例,但在不传递值的情况下无法调用构造函数。这就是为什么它会破裂。然后,如果它找到一个String值(一个空的String bean,它被匹配为唯一一个与依赖项注入相匹配的对象),它将使用它来创建对象,然后通过@Value注释设置该值。

您可以尝试删除bean的构造函数(和@RequiredArgsConstructor),它应能按预期工作,因为所有属性将使用反射注入,并且将调用默认的no args构造函数。

另一个不错的解决方案,以一种“ Spring”的方式看起来不错,它是使用您要在配置中注入的真实值添加Bean,并且没有@Value注释-只需使用构造函数进行初始化的豆子。当前,您正在混合它-其中一部分来自构造函数,另一部分稍后设置。

也许最好的方法(应该是我应该写的最好的方法)是将该值注释添加到构造函数字段中。然后它将使用该值而不是搜索bean。

@Service
@RequiredArgsConstructor //Lombok
public class SomeService {

   private final String someValue;
   public SomeService(@Value("${value.to.be.injected}") String someValue, other stuff....) { 
     this.someValue=someValue;
   }
}