首页 > 解决方案 > Spring Boot 自动装配:属性值被填充的奇怪情况

问题描述

在发现我的代码从过去 2 年开始正常工作而显然不应该工作后,我被某事震惊了,我的睡眠无处可去!所以它是一个 Spring Boot 应用程序。该应用程序有一些控制器。我正在使用的类之一扩展了 WebServiceGatewaySupport,因此需要我 @Autowire 这个。类名是 AClient。现在,这个类需要 4 个属性才能工作。其中三个来自属性文件,例如

@Value("${a.userName}")String userName; 

所以三个属性显然是从 application.properties 文件中挑选出来的。现在第四个属性让我大吃一惊。它不是作为其余三个被提取的,而是从构造函数参数中复制的。所以我们在类中只有一个构造函数:

public AClient(String d){
    this.d=d;
}

现在这个属性被用在这个类的方法之一中

public String getSomeData(){
// This method gets Data based on property d
}

有趣且令人惊讶的是,每次访问此 bean 时都会显示此属性的值!bean 仅在 Controller 类中的一个地方使用 @Autowired。我没有标记要从 application.properties 文件中获取的属性值。我没有为这个类提供任何从哪里获取 d 值的线索。我没有为其他类提供任何公共方法来设置这个值。然而代码正在运行,我什至可以在 getSomeData() 方法中放置一个调试指针,然后查看 d 的值是否存在!

现在我明白我可能遗漏了一些明显的东西,但是什么?当 @Autowired 对象被实例化并从该点调试以查看该值的来源时,有没有办法可以进入 Spring 容器?我已经多次检查代码。在 Google 上运行数百个查询,以找到类似 Spring boot 之类的东西来映射缺失的 String 属性。但是属性文件中的变量名与 AClient 类中的不同。那么它怎么能映射呢?这下真的要死我了!

补充:相关性较低,但以标准方式访问代码:

@Autowired
AClient aClient;

public someOtherMethod(){
    aClient.getSomeData();
}

因此,当我将调试器放在 someOtherMethod() 的第一行并将鼠标悬停在 aClient 上时,它会显示填充的变量 d 值,与 application.properties 文件中的相同!

编辑:这是我错过的:

@Configuration
public class someConfig{
@Bean
   public AClient aClient(){
    // Someone else fetched property from application.properties file, created an object of AClient class using argument constructor and returned that object here. So now Spring is using @Autowire reference for this object I guess
 }
}

标签: javaspringspring-bootautowired

解决方案


所以基本上,你的@Configuration课看起来和这个很相似?

@Configuration
public class SomeConfig {

    @Value("${a-client.important-value-d}")
    private String importantValueDFromApplicationProperties;

    @Bean
    public AClient aClient() {
        return new AClient(importantValueDFromApplicationProperties);
    }

}

如果是,那么 Spring 将为aClient每个@Autowired请求它。因此 的值importantValueDFromApplicationProperties将出现在这个特定的实例中。

另一个注意事项:我建议使用 Spring Boot@ConfigurationProperties而不是@Value. 看一看。


推荐阅读