【发布时间】: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