D-Dᴙum
D-Dᴙum

Reputation: 7890

Instantiate Bean on Demand With Runtime-Defined Configuration

In my application I would like to instantiate a class on demand and pass some runtime parameters to is as well as have Spring automatically fulfil any @Autowired dependencies. For example, the class I would like to instantiate on demand:

@Service
@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public class FileProcess implements Runnable
{
    @Autowired
    private MyDAO myDAO;

    private String configOne;

    private String configTwo;

    @Override
    public void run()
    {
    }
}

The object myDAO exists already within the ApplicationContext and I would like Spring to fulfil this dependency for me. Indeed any instantiation of this class shouldn't really know the internals of FileProcess only that it requires the configuration parameters configOne and configTwo

To get an instance of FileProcess I have use the getBean() method of the ApplicationContext but I am unable to pass in only the configuration parameters:

final FileProcess fileProcess = this.applicationContext.getBean(FileProcess.class, configOne, configTwo)

This results in the error:

Could not resolve matching constructor (hint: specify index/type/name arguments for simple parameters to avoid type ambiguities

I have found that no matter what constructor I add to FileProcess I get the same error. I would like to only have to pass in the configuration parameters and not, in this case not an instance of MyDAO. Again, having to pass in an instance of MyDAO means the caller must have knowledge of the internals of FileProcess and in general must be aware of the scope of such beans.

Is there a way I can achieve this without having to resort to a @Configuration class and a @Bean annotated method?

Upvotes: 0

Views: 241

Answers (1)

daniu
daniu

Reputation: 14999

I think you'd be best off with a factory bean, like

@Bean
BiFunction<String, String, FileProcess> createFileProcess(MyDAO dao) {
    return (c1, c2) -> {
        FileProcess result = new FileProcess(dao) ;
        result.setConfig1(c1);
        result.setConfig2(c2);
        return result;
   };
}

This in a configuration class, and you can Autowire it to create the process object with your config values.

@Autowired
BiFunction<String, String, FileProcess> processFactory;
... 
FileProcess p = processFactory.apply("val1", "val2");

Upvotes: 1

Related Questions