@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&lt;Data, Long&gt;)? 是的,但当然会发生在 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

@Autowired取不到

Spring基于注解的配置之@Autowired

@Autowired 在 Spring 中的类上

多线程时Autowired自动注入问题