【问题标题】:Spring boot autowiring: strange case of property value being populatedSpring Boot 自动装配:属性值被填充的奇怪情况
【发布时间】:2020-06-02 23:55:02
【问题描述】:

在发现我的代码从过去 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
 }
}

【问题讨论】:

  • 您是否在某处将 String d 的实例定义为 @Bean?
  • 哦!对所有班级进行扫描。其他开发人员之一确实专门创建了 Configuration 类,以确保仅从属性文件中填充此值。这就是这个@Autowired 对象的来源!!不是来自我正在追逐的构造函数!
  • 不敢相信我错过了这个!非常感谢@Manuel :-)
  • 你能提供一个minimal, reproducible example吗?编辑:没关系,看起来你找到了。
  • @silentsudo:有趣的是,当测试抛出属性丢失的错误时,我正在进行单元测试。这让我感到惊讶的是代码在测试用例之外工作。我想这一切都是为了了解 XML 配置确实有它的好处,其他开发人员无法用隐藏的配置给你惊喜 :-)

标签: java spring spring-boot autowired


【解决方案1】:

所以基本上,您的@Configuration 类看起来与此类似?

@Configuration
public class SomeConfig {

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

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

}

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

另一个说明: 我建议使用 Spring Boot 的 @ConfigurationProperties 而不是 @Value。看看吧。

【讨论】:

    猜你喜欢
    • 2015-03-08
    • 2010-12-30
    • 2019-04-21
    • 2014-11-05
    • 1970-01-01
    • 2018-11-14
    • 1970-01-01
    • 2015-04-23
    • 2017-09-07
    相关资源
    最近更新 更多