【问题标题】:How to create a bean by type in Spring?如何在 Spring 中按类型创建 bean?
【发布时间】:2017-01-13 20:27:39
【问题描述】:

在我的 ApplicationContext 中,我创建了几个相同样式的 Bean。所以我有很多重复的代码为每个 bean 编写 FactoryBean。这些 bean 有一个共同点,都实现了一个特殊的接口。

我想将所有 bean 创建移到一个工厂。那必须提供这样的方法

<T extends CommonInterface> T createInstance(Class<T> clazz);

在那里我可以实现创建我的一个特殊 bean 所需的所有实例化。

我的实现将由 spring 调用

@Autowired
private MyCommonInterfaceImplementation impl;

这样

createInstance(MyCommonInterfaceImplementation.class)

到目前为止,我查看了BeanFactoryFactoryBean,似乎都不是我要寻找的。​​p>

有什么建议吗?

【问题讨论】:

  • 你为什么不使用@Component注解?
  • @MartinFrey,组件注释在这种情况下有何帮助?可能是我完全理解问题,但在这种情况下,我的这种情况注释不是解决方案

标签: java spring spring-ioc


【解决方案1】:

为什么不使用@bean

@Bean
public MyCommonInterfaceImplementation getMyCommonInterfaceImplementation(){
    return MyBeanFactory.createInstance(MyCommonInterfaceImplementation.class);
}

//should autowire here
@Autowired
private MyCommonInterfaceImplementation impl;

【讨论】:

  • 好吧,这比每次都实现一个FactoryBean要好得多。但是我有大约 30 个 Bean 导致 30 个 @Bean 方法都在做同样的事情。能够按其类创建 bean 将是一个很大的帮助。
【解决方案2】:

基本上,只有在创建 bean 期间需要一些特殊处理时,您才需要在“工厂”上添加 @Bean 注释。

如果一切都可以是@Autowired,无论是通过setter、fields还是一个构造函数,并且在初始化期间不需要对bean做任何其他事情,你可以简单地在你的接口的每个实现上声明@Component。只要您在应用程序中激活了component scanning,它就可以工作。结果是,对于每个组件,spring 都会创建一个您可以使用的 bean。

我是在手机上写的,所以显示代码不是最好的。只需按照 @ComponentScan 上的一些教程进行操作,或者如果您需要,请告诉我,我可以通过示例来扩充这个答案。

【讨论】:

    【解决方案3】:

    从 Spring 4.3 开始,您不再需要注释 bean 类,您可以让它们通过组件扫描来实例化。

    @Configuration @ComponentScan( value = "some.package.path", includeFilters = { @Filter(type = ASSIGNABLE_TYPE, value = { MyClass1.class, MyClass2.class, MyClass3.class }) })

    这实际上为列出的三个类创建了 bean。该示例也应该在没有过滤器的情况下工作(包中的所有内容都变成了一个 bean)。只要这些类有一个可用于自动装配的构造函数,它就可以工作。我认为不可能过滤特定接口的所有实现,然后注册一个 bean。

    为此,您可以使用 ContextListener 和例如使用反射找出要实例化的类,然后使用 context.autowire(..) 从您的上下文中注入任何依赖项。有点hacky,但它可能会工作。

    @Override public void onApplicationEvent(ContextRefreshedEvent event) { ApplicationContext context = event.getApplicationContext(); MyClass bean = context .getAutowireCapableBeanFactory() .autowire(MyClass.class, Autowire.BY_NAME.value(), true); ... }

    当然,这仍然留下了如何在上下文中注册 bean 的问题。

    您还可以调整this SO question 的答案,了解如何以编程方式添加 bean。

    【讨论】:

      【解决方案4】:

      最后我发现最好的方法是使用ConfigurationClassPostProcessor。例如,我使用了https://github.com/rinoto/spring-auto-mock

      但是,由于从无到有创建 bean 非常复杂且“太神奇”,因此我们决定通过 @Bean 显式创建这些 bean。

      感谢您的回答。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-11-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-01-01
        相关资源
        最近更新 更多