Spring注入的bean不是@Configuration中指定的bean
最近,我在Spring中连接bean时出错,导致无法复制的行为。当部署应用程序时,使用了Spring注入的bean不是@Configuration中指定的bean,spring,spring-boot,kotlin,properties-file,spring-annotations,Spring,Spring Boot,Kotlin,Properties File,Spring Annotations,最近,我在Spring中连接bean时出错,导致无法复制的行为。当部署应用程序时,使用了@Configuration中定义的@String类型的另一个bean的值,而不是源于@Value的属性注入内容(请参阅下面的完整演示代码) 我发现令人费解的是,在本地运行(包括单元测试)时,一切都按预期工作,输出是foo而不是kaboom,并且这种“bean交换”完全是在部署时发生的,而不是“没有符合条件的bean”错误 注释掉的行显示了修复,我认为它使配置与中的配置相似 我的设置有什么问题?什么会使所示代
@Configuration
中定义的@String
类型的另一个bean的值,而不是源于@Value
的属性注入内容(请参阅下面的完整演示代码)
我发现令人费解的是,在本地运行(包括单元测试)时,一切都按预期工作,输出是foo
而不是kaboom
,并且这种“bean交换”完全是在部署时发生的,而不是“没有符合条件的bean”错误
注释掉的行显示了修复,我认为它使配置与中的配置相似
我的设置有什么问题?什么会使所示代码(即没有修复)使用kaboom
String
而不是foo
属性
import org.springframework.boot.autoconfigure.springboot应用程序
导入org.springframework.boot.runApplication
@SpringBoot应用程序
开放类演示应用程序
趣味主线(args:Array){
运行应用程序(*args)
}
import org.springframework.beans.factory.annotation.Value
导入org.springframework.context.annotation.Bean
导入org.springframework.context.annotation.Configuration
@配置
开放类配置{
//…原始代码中不是字符串类型的bean。。。
@豆子
打开有趣的beanBomb():字符串{
返回“kaboom”
}
@豆子
//修正:
//@Value(\${stuff})
打开有趣的beanStuff(stuff:String):stuff{
退货
}
}
import org.springframework.beans.factory.annotation.Value
导入org.springframework.stereotype.Component
@组成部分
类Stuff(@Value(\${Stuff})val Stuff:String)
import org.springframework.beans.factory.annotation.Autowired
导入org.springframework.stereotype.Component
导入javax.annotation.PostConstruct
@组成部分
类初始化{
@自动连线
私有lateinit var stuff:stuff
@施工后
fun init(){
println(“stuff:+stuff.stuff)
}
}
导入静态org.junit.jupiter.api.Assertions.assertEquals;
导入org.junit.jupiter.api.Test;
导入org.junit.jupiter.api.extension.extensedWith;
导入org.springframework.boot.test.mock.mockito.SpyBean;
导入org.springframework.test.context.TestPropertySource;
导入org.springframework.test.context.junit.jupiter.SpringExtension;
@ExtendWith(SpringExtension.class)
@TestPropertySource(属性={“stuff=testFoo”})
类DemoApplicationTests{
@间谍
私人物品;
@试验
无效测试(){
assertEquals(“testFoo”,stuff.getStuff());
}
}
另外,一旦应用了修复程序,Stuff
中的@Value
注释是否必要?如果我取消对修复的注释,请从Stuff
中删除@Value
,并向测试通过的测试类添加以下注释:
@ContextConfiguration(classes={Config.class})
但是当我运行应用程序时,它会打印出kaboom
…,您可以检查bean的创建顺序。如果bean是在我看来之前创建的,Spring IoC容器按类型注入值,即kaboom
,并且由于默认情况下任何类型的bean都是单例的,Stuff
的实例即使用@component
注释也不会生效
在您的测试中,您正在手动加载配置,其中Config
中定义的Stuff
bean被注入,而不是Stuff
被@component
注释。问题是注释需要在参数上进行,而不是在函数上。
以您的方式,Spring正在寻找一个满足String
类型的bean,并且有一个String
类型的bean是由函数beanBomb()
生成的。如果像这样移动注释,则应消除歧义
@Bean
打开有趣的beanStuff(@Value(\${stuff})stuff:String):stuff{
退货
}
我想补充一点,有一个类型为String
的bean有点不寻常,但我想如果你不想使用属性/yaml文件,它会允许你根据配置文件更改字符串。所以原始代码的问题是我在两个地方创建bean东西
(@Bean
vs@Component
),其中一个从@Value
注释中获取参数,另一个从Config
中创建的字符串bean中获取参数。当我在本地运行时,Spring创建了@组件注释填充填充来自@Value
,而在部署应用程序时Spring必须创建了@Bean
注释的Stuff
,其中Stuff
来自beanBomb()
。正确吗?如果是这样的话,很遗憾Spring没有警告多个bean声明,而是从批中挑选任何一个。是的,可能是..您可以添加一个调试器点或添加一些日志消息,只是为了确定bean的创建顺序,其他选项是使用@Priority
或@order
annota将@Component
注释放在Stuff
类上,同时在java配置(带有@Bean
注释的方法)中定义它有什么意义?
// application.properties
stuff=foo