Java SpringBoot应用程序需要在@Configuration类中定义默认bean才能使用@Value?

Java SpringBoot应用程序需要在@Configuration类中定义默认bean才能使用@Value?,java,spring,spring-boot,Java,Spring,Spring Boot,最近,我遇到了一个相当奇怪的情况 请考虑一个简单的Spring启动应用程序: @SpringBootApplication public class SampleApp implements WebMvcConfigurer { public static void main(String[] args) { SpringApplication.run(SampleApp.class, args); } } 在这个SampleApp中,我们有一个配置类

最近,我遇到了一个相当奇怪的情况

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

@SpringBootApplication
public class SampleApp implements WebMvcConfigurer {

    public static void main(String[] args) {
            SpringApplication.run(SampleApp.class, args);
    }
}
在这个SampleApp中,我们有一个配置类,例如:

@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会这样做?

我的猜测是,您在构造函数中添加了“someValue”,它尝试创建实例,但在不传递值的情况下无法调用构造函数。这就是它破裂的原因。然后,如果它找到一个字符串值(一个空的字符串bean,它被匹配为唯一适合依赖项注入的值),它将使用它来创建对象,然后根据@value注释设置值

您可以尝试删除bean的构造函数(和@RequiredArgsConstructor),它应该可以正常工作,因为所有属性都将使用反射注入,并且它将调用默认的无参数构造函数

另一个很酷的解决方案,看起来不错,而且更“Spring”的方式是,添加具有您想要注入到配置中的实际值的bean,而不是@value注释——只需使用构造函数初始化bean即可。目前您正在混合它-部分内容来自构造函数,另一部分稍后设置

也许最好的方法(也许我应该先写)是将这个值注释添加到构造函数字段中。然后它将使用该值,而不是搜索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;
   }
}