根据外部配置创建多个相同类型的bean

问题描述

class SomeClass() implements Runnable
{
    private SomeDevice someDevice;
    private SomeOtherDevice someOtherDevice;
    
    @Override
    public void run()
    {
        ...
        someDevice.doSomething();
        ...
        someOtherDevice.doSomething();
    }
}
@Configuration
class Config
{
    @Bean
    @Scope("prototype")
    public SomeDevice someDevice { return new SomeDevice() }
    @Bean
    @Scope("prototype")
    public SomeOtherDevice someOtherDevice { return new SomeOtherDevice() }
}

我是Spring的新手,实现起来有点复杂。

我有一个外部配置文件,该文件指定我将拥有多少个SomeDevice,以及每个SomeDevice将监听的端口。 SomeClass的实例将负责每个SomeDevice。因此,我将在SomeClass1内部运行SomeDevice1,在SomeClass2内部运行SomeDevice2,等等。 每个SomeClass也将需要其自己的SomeOtherDevice实例。

我希望能够手动创建这些bean,以便可以:

  1. 读取我的外部配置文件并创建适当数量的SomeDevice
  2. 通过调用someDevice.setPort()根据外部配置指定每个端口
  3. 将它们放入自己的SomeClass实例中。
  4. SomeClass也将需要它自己的SomeOtherDevice实例(SomeOtherDevice不需要外部配置信息)

我尝试使用bean工厂来执行此操作,但是在使用bean工厂创建它们后,我很难让SomeClass找到SomeDevice bean。它无法按名称找到它们,只能按类找到它们。但是因为要有多个SomeDevice.class Bean,所以我希望能够按名称查找它们(并在创建它们时给它们提供唯一的名称)。我什至也不确定我是否以“最佳”方式来对待事情。如果有人能指出正确的方向,我将不胜感激。

编辑:我忘了提到我不想更改SomeDevice的源代码。因此,除非非常必要,否则我无法在该类中添加Spring注释。

解决方法

您通常不希望通过解析外部配置来创建bean。那将是对Spring框架的彻底改造,并且由于您说自己是Spring的新手,所以您会弄错它。 您想要的是有条件地激活您想要的bean。因此,您将有多个SomeClassSomeDevice,但是根据运行时(外部)配置,只会创建一个或多个bean。 请参阅文档的this部分。

如果您不知道如何编写自己的条件,请在Google上进行搜索。您也可以从“ Spring Boot配置文件”开始,它是所有条件中最简单的,并且是OOTB。

编辑: 如果必须读取外部文件并在运行时注册Bean,请参见this教程。但是,通常有如上所述的更简便方法。