英文:
Creating multiple beans of same type based on external config
问题
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(); }
}
I'm very, very new to Spring and have a bit of a complex thing to implement.
I have an external configuration file that specifies how many of SomeDevice I will have, as well as what port each of SomeDevice will be listening on.
An instance of SomeClass will be in charge of each SomeDevice. So I'll have SomeDevice1 running inside SomeClass1, SomeDevice2 running inside SomeClass2, etc.
Each SomeClass will also need its own instance of a SomeOtherDevice.
I wanted to be able to create these beans manually so that I can:
- Read my external config file and create the proper number of SomeDevice(s)
- Specify each of their ports as per the external config by calling someDevice.setPort()
- Put these inside their own instances of SomeClass.
- SomeClass will also need its own instance of SomeOtherDevice (SomeOtherDevice does not need external config info)
I've tried using bean factories to do this and I'm having trouble getting SomeClass to find the SomeDevice beans after I create them using bean factories. It can't find them by name, only by class. But because I'm going to have multiple SomeDevice.class beans, I want to be able to find them by name (and give them unique names when I create them). I'm also not even sure I'm approaching things in the "best" way. If anyone could point me in the right direction, I'd really appreciate it.
EDIT: I forgot to mention that I would prefer not to change the source code of SomeDevice. So I can't add Spring annotations to that class unless it would be extremely necessary.
<details>
<summary>英文:</summary>
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() }
}
I'm very, very new to Spring and have a bit of a complex thing to implement.
I have an external configuration file that specifies how many of SomeDevice I will have, as well as what port each of SomeDevice will be listening on.
An instance of SomeClass will be in charge of each SomeDevice. So I'll have SomeDevice1 running inside SomeClass1, SomeDevice2 running inside SomeClass2, etc.
Each SomeClass will also need its own instance of a SomeOtherDevice.
I wanted to be able to create these beans manually, so that I can:
1. Read my external config file and create the proper number of SomeDevice(s)
2. Specify each of their ports as per the external config, by calling someDevice.setPort()
3. Put these inside their own instances of SomeClass.
4. SomeClass will also need it's own instance of SomeOtherDevice (SomeOtherDevice does not need external config info)
I've tried using bean factories to do this and I'm having trouble getting SomeClass to find the SomeDevice beans after I create them using bean factories. It can't find them by name, only by class. But because I'm going to have multiple SomeDevice.class beans, I want to be able to find them by name (and give them unique names when I create them). I'm also not even sure I'm approaching things in the "best" way. If anyone could point me in the right direction, I'd really appreciate it.
EDIT: I forgot to mention that I would prefer not to change the source code of SomeDevice. So I can't add Spring annotations to that class unless it would be extremely necessary.
</details>
# 答案1
**得分**: 1
通常情况下,您不希望通过解析外部配置来创建 beans。那样会相当于重新发明 Spring 框架,而且考虑到您表示您对 Spring 还不熟悉,可能会出错。
您想要的是根据条件激活所需的 beans。因此,您将拥有多个 `SomeClass` 和 `SomeDevice`,但只会根据运行时(外部)配置创建一个或多个 beans。
查看[此链接](https://docs.spring.io/spring-boot/docs/1.2.1.RELEASE/reference/html/boot-features-developing-auto-configuration.html)中的文档部分。
如果您不知道如何编写自己的条件,可以搜索一下。您还可以从“Spring Boot 配置文件”开始,这是最简单的条件之一,并且已经预先提供了。
**编辑:**
如果您必须在运行时读取外部文件并注册 beans,可以参考[这篇教程](https://www.baeldung.com/spring-5-functional-beans)。然而,通常存在以上描述的更简单的方法。
<details>
<summary>英文:</summary>
You usually don’t want to be creating beans by parsing external configuration. That’ll be reinventing the Spring framework, and since you say you’re new to Spring, you’ll get it wrong.
What you want is to conditionally activate the beans you want. So, you’ll have multiple `SomeClass` and `SomeDevice`, but only one or more beans will be created depending on runtime (external) configurations.
See [this](https://docs.spring.io/spring-boot/docs/1.2.1.RELEASE/reference/html/boot-features-developing-auto-configuration.html) portion of the docs.
If you don’t know how to write your own conditions, google it. You can also start with “Spring Boot profiles”, which is the simplest of all conditionals, and comes OOTB.
**Edit:**
If you must read an external file and register beans at runtime, see [this](https://www.baeldung.com/spring-5-functional-beans) tutorial. However, usually there are easier ways as described above.
</details>
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论