在 Spring 中将原型列表注入 Singleton bean

Posted

技术标签:

【中文标题】在 Spring 中将原型列表注入 Singleton bean【英文标题】:Injecting List of Prototypes into Singleton bean in Spring 【发布时间】:2016-09-30 22:08:14 【问题描述】:

在这里春天需要一些帮助。 在我们的项目中,我们使用 XML 和注释配置(Spring 4.1) 最近我面临以下任务:

我有一个范围为 prototype 的 bean 列表,它们都实现了相同的接口。

此外,我还有一个具有execute 方法的单例bean。在方法内部,bean 应该访问这些原型 bean 的列表。

每次执行“执行”方法时,我都希望能够访问这些原型 bean 的不同实例)。 在单例中,我没有预先知道完整的 bean 列表,所以我只是 @Autowire 整个集合,以便加载应用程序上下文中已知的每个 bean 实现。

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???
   

 

所以我的问题是:实现这一目标的最干净的方法是什么?理想情况下,我希望得到一个完全与 spring 接口分离的解决方案(比如注入 ApplicationContext/BeanFactory 的东西) 我不介意在这里使用 Aop(性能不是那么重要),但我不能真正将头绕在一个干净的弹簧解决方案上。因此,我们将不胜感激。

提前致谢

【问题讨论】:

【参考方案1】:

我一直在尝试使用 Spring 实现类似的目标,在使用 ServiceLocatorFactoryBean 或 method injection (with @Lookup) 阅读 Spring 文档后,我发现并看起来很有希望。 然而,在尝试了这两种方法后,结果却令人沮丧。两种方式都不支持在 List 中返回 bean。我得到了这个例外:

没有可用的“java.util.List”类型的合格 bean

显然 Spring 将返回类型视为常规对象。

所以最终我的解决方案变成了创建一个新对象来将列表包装为返回类型。

@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;
    

然后为 List Object 创建一个 Factory 类:

@Component
public interface ProcessorFactory

    ProcessorList getProcessorList();

然后使用ServiceLocatorFactoryBean注册工厂:

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


最后实现接口并确保用@Scope("prototype")标记它们

现在您每次使用工厂方法时都会获得新实例!

如果你愿意,它类似于使用方法注入。

【讨论】:

以上是关于在 Spring 中将原型列表注入 Singleton bean的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Spring Boot 中将属性注入测试类?

如何在spring boot中将@Value属性从application.properties注入@InjectMocks?

在Spring上下文中的原型bean中的单例bean

Spring会话范围的bean作为原型bean中的依赖项?

何时使用 Spring 原型作用域?

Spring框架参考手册(4.2.6版本)翻译——第三部分 核心技术 6.5.3 依赖于原型Bean的单例Bean