Mark Bramnik
Mark Bramnik

Reputation: 42441

Injecting List of Prototypes into Singleton bean in Spring

Need some help in spring here. In our project we use XML and annotation configurations (Spring 4.1) Recently I've faced the following task:

I have a list of beans of scope prototype, all of them implement the same interface.

In addition I have one singleton bean that has execute method. Inside the method the bean should access the list of those prototype beans.

Every time the 'execute' method gets executed I would like to get the access to the different instances of those prototype beans). In singleton I don't have the whole list of beans known in advance, so I just @Autowire the whole collection so that every bean implementation known in the application context will be loaded.

interface SomeInterface {

}


class PrototypeBean1 implements SomeInterface {
  ...
}

class PrototypeBean2 implements SomeInterface {
  ...
}


class MySingletonBean {

   @Autowire (????)
   List<SomeInterface> allPrototypeBeansLoadedIntoTheApplicationContext;

   public void execute() {
      // this one is called many times,
      // so I would like to get different lists of    
      //"allPrototypeBeansLoadedIntoTheApplicationContext"
      // with different actuals bean upon every invocation
      // how do I achieve this???
   }

} 

So my question is: What is the most clean way to achieve this? Ideally I would like to get a solution totally decoupled from spring interfaces (like injecting ApplicationContext/BeanFactory stuff) I don't mind to use Aop here (performance is not that critical), but I can't really wrap my head around a clean spring solution. So any help will be appreciated.

Thanks in advance

Upvotes: 1

Views: 1376

Answers (1)

YQJ
YQJ

Reputation: 51

I have been trying to achieve similar goal with Spring and after reading Spring docs using either ServiceLocatorFactoryBean or method injection (with @Lookup) came up and looked promising. However after tried both approach results turned out to be frustrating. Neither way supports returning beans in List. And I got this exception:

No qualifying bean of type 'java.util.List' available

Apparently Spring treated the return type as a regular Object.

So eventually my solution became creating a new object to wrap the list as return type.

@Component
@Scope("prototype")
public class ProcessorList
{
    private List<Processor> processors;

    public ProcessorList(List<Processor> processors)
    {
        this.processors = processors;
    }

    public List<Processor> getProcessors()
    {
        return processors;
    }

    public void setProcessors(List<ChangeSetProcessor> processors)
    {
        this.processors = processors;
    }
}

then create a Factory class for the List Object:

@Component
public interface ProcessorFactory
{
    ProcessorList getProcessorList();
}

Then use ServiceLocatorFactoryBean to register the factory:

@Configuration
public class MyConfiguration{
    @Bean
    public FactoryBean serviceLocatorFactoryBean()
    {
        ServiceLocatorFactoryBean factoryBean = new ServiceLocatorFactoryBean();
        factoryBean.setServiceLocatorInterface(ProcessorFactory.class);
        return factoryBean;
    }

}

Finally implement the interface and make sure mark them all with @Scope("prototype")

Now you'll get new instance each time you use the factory method!

It's similar to use method injection if you prefer.

Upvotes: 1

Related Questions