【问题标题】:@Autowired based on a property inside application.properties@Autowired 基于 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 发出警告

标签: java spring-boot dependency-injection kotlin autowired


【解决方案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
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-12-02
      • 2019-03-15
      • 2017-09-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-07-02
      • 1970-01-01
      相关资源
      最近更新 更多