Creating multiple beans of same type based on external config

Tags: , , ,



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.

Answer

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 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 tutorial. However, usually there are easier ways as described above.



Source: stackoverflow