@Autowired 基于 application.properties 中的属性
Posted
技术标签:
【中文标题】@Autowired 基于 application.properties 中的属性【英文标题】:@Autowired based on a property inside application.properties 【发布时间】:2018-09-24 12:30:47 【问题描述】:假设我有几个 Spring 组件实现了一个接口:
interface Haha
@Component class HahaImpl1: Haha
@Autowired lateinit var repo: JpaRepository<Data, Long>
@Component class HahaImpl2: Haha
@Service
class Yoyo
@Autowired lateinit var haha: Haha
如何将正确的依赖项注入我的Yoyo
服务,我可以在application.properties
文件中指定?
myApp.haha=impl1
我可以创建一个配置,但是我必须删除 @Component
注释,这是我不想要的,因为在哈哈实现类中我会注入其他 bean(服务、控制器等):
@Configuration
class MyConfiguration
@Bean
@ConditionalOnProperty(name = ["myApp.haha"], havingValue = "impl1", matchIfMissing = true)
fun config1(): Haha = HahaImpl1()
@Bean
@ConditionalOnProperty(name = ["myApp.haha"], havingValue = "impl2")
fun config2(): Haha = HahaImpl2()
有什么想法吗?谢谢。
【问题讨论】:
这是我不想要的,因为在哈哈实现类中我会注入其他 bean:你不需要 Component 注释来拥有它。您只需要将对象设为 Spring bean,它就是这样,因为您从@Bean
-annotated 方法返回它。
@JBNizet 你的意思是在 bean 实例化期间(比如说config1()
),Spring 会查看 HahaImpl1
类并自动装配它的所有依赖项(repo: JpaRepository<Data, Long>
)?
是的,但当然会发生在 bean 实例化之后。不在此期间。
@JBNizet 我很困惑,因为 Intellij 2017.3 在 haha 属性上抛出了一个高亮警告:coudn't autowire: there's more than one bean of 'Haha' type
。而在HahaImpl1
@Autowired 内部则使用Autowired members must be defined in valid Spring beans
发出警告
【参考方案1】:
您可以通过将@ConditionalOnProperty
移动到您的bean 类并完全删除@Configuration
类来解决问题(或者至少删除处理HaHa
实例的部分):
interface HaHa
@Component
@ConditionalOnProperty(name = "myApp.haha", havingValue = "impl1", matchIfMissing = true)
class HahaImpl1: Haha
@Autowired
lateinit var repo: JpaRepository<Data, Long>
@Component
@ConditionalOnProperty(name = "myApp.haha", havingValue = "impl2")
class HahaImpl2: Haha
// ...
这样你总是会得到一个HaHa
的实例,并且仅基于是否存在属性。这是因为@ConditionalOnProperty
可以出现在Method or a Type 上。
【讨论】:
【参考方案2】:解决办法是把@Component
注解从所有的Haha实现类中去掉。
interface Haha
class HahaImpl1: Haha
@Autowired lateinit var repo: JpaRepository<Data, Long>
class HahaImpl2: Haha
@Service
class Yoyo
@Autowired lateinit var haha: Haha
@Configuration
class MyConfiguration
@Bean
@ConditionalOnProperty(name = ["myApp.haha"], havingValue = "impl1", matchIfMissing = true)
fun config1(): Haha = HahaImpl1()
@Bean
@ConditionalOnProperty(name = ["myApp.haha"], havingValue = "impl2")
fun config2(): Haha = HahaImpl2()
application.properties
:
myApp.haha=impl1
#myApp.haha=impl2
【讨论】:
以上是关于@Autowired 基于 application.properties 中的属性的主要内容,如果未能解决你的问题,请参考以下文章
SpringBoot 中@Autowired 注入失效原因及解决方法
Spring Boot @Autowired无法注入类 Consider defining a bean of type