【问题标题】:Create multiple beans from one method in @Configuration class从@Configuration 类中的一种方法创建多个bean
【发布时间】:2014-12-31 12:56:14
【问题描述】:

我是 DI 的 Spring,我使用 XML。

基于配置(例如 xml/properties 文件),我希望创建一些特定类型的 bean(确切数量由配置确定)放入我的上下文中,以便它们可以自动装配到类。

我会自动接线:@Autowired public MyClass(List<MyType> types)

我正在考虑使用带有 @Configuration 注释的类。

所以我可以这样做:

@Configuration
public MyConfigurationClass {

    @Autowired
    public void configure(ApplicationContext context) {
        // register stuff here
    }
}

...但它“感觉”不对...

实现这一点的“Spring”方式是什么?

编辑:

想象一下这段代码,其中ToTy 只是空的类定义。

@Configuration
public class Config {

    @Bean
    public Collection<Ty> tyList() {
        return new ArrayList<Ty>() {{
            this.add(new Ty()); // could be any number of Ty instances.
        }};
    }

    @Bean
    public To to(Collection<Ty> tylist) {
        return new To();
    }
}

【问题讨论】:

  • “将可变数量的类实例放入 Spring 上下文”到底是什么意思?
  • @Dodge - 我的编辑对你来说更有意义吗?
  • 为什么不创建多个@Bean 方法?
  • @Cheetah 如果我正确理解您的意图,请查看我的答案。
  • @SotiriosDelimanolis - 请参阅编辑...我没有明确表示 bean 计数与配置中的内容直接相关。我不知道编译时的 bean 计数。

标签: java spring


【解决方案1】:

我不确定我是否理解正确,但我相信这就是你想要的。

public interface MyStuff {
  void doSomething();
}

@Scope("prototype") // 1
@Service("stuffA") // 2
public class MyStuffImpl_A implements MyStuff {
  public void doSomething()
  {
     // do your stuff
  }
}

@Scope("prototype")
@Service("stuffB")
public class MyStuffImpl_B implements MyStuff {
  public void doSomething()
  {
     // do your stuff the B way ;)
  }
}

现在你可以这样做了:

public class UseTheStuff {

  @Autowired
  private Provider<MyStuff> stuffA; // 3

  @Autowired
  private Provider<MyStuff> stuffB;  // 4

  public void doStuffWithTheProvider(){
    MyStuff stuffA.get(); // 5
    MyStuff stuffB.get(); // 6
  }
}
  1. 告诉 spring 使用这个实现作为原型
  2. 将此实现命名为 MyStuff:“stuffA”
  3. 获取一个提供者(名称“stuffA”告诉 spring 注入一个 MyStuffImpl_A 提供者)
  4. 获取一个提供程序(名称“stuffB”告诉 spring 注入一个 MyStuffImpl_B 提供程序)
  5. 使用提供程序创建 MyStuffImpl_A 的实例
  6. 使用提供程序创建 MyStuffImpl_B 的实例

【讨论】:

  • 我认为,它看起来不像 OP 所要求的。他希望通过指定创建次数来以编程方式创建 bean,在应用程序上下文实例化之后应该创建多少个 bean。此外,他想使用@Configuration注解,这表明spring必须将标记的类保持为bean蓝图类(类似于xml文件)
  • @energyr 可能。如前所述,我不确定这是否是他想要做的。至少这是一个尝试帮助:-)
【解决方案2】:

如果您不需要单独的限定符并且可以自动装配为列表,您可以在 Spring 4 中执行此操作:

@Configuration
public MyConfigurationClass {

    @Bean
    public List<MyType> configure() {
        //create your dynamical list here
    }
}

但是对于 Spring 3(泛型被忽略),你会更安全地使用:

@Configuration
public MyConfigurationClass {

    @Bean
    @Qualifier("mylist")
    public List<MyType> configure() {
        //create your dynamical list here
    }
}

和自动接线:

@Autowired public MyClass(@Qualifier("mylist") List<MyType> types)

有了这个,你就不需要直接接触 ApplicationContext 实例了。这不是很好的做法。

编辑:

你试过了吗?:

@Configuration
public class Config {

    @Bean
    @Qualifier("tylist")
    public Collection<Ty> tyList() {
        return new ArrayList<Ty>() {{
            this.add(new Ty()); // could be any number of Ty instances.
        }};
    }

    @Bean
    public To to(@Qualifier("tylist") Collection<Ty> tylist) {
        return new To();
    }
}

【讨论】:

  • 嗯,我发誓我试过你的第一个例子 - 让我再试一次。
  • 你能用这个自动装配发布课程吗:“我会自动装配:@Autowired public MyClass(List types)”
  • 没关系。指定了两个bean:类型为“Collection”和类型为“To”的第二个。此外,Spring 应该将“Collection”类型的 bean 注入到 to() 方法中。有什么问题?
  • Spring 在抱怨没有任何 Ty 对象可以自动装配。
【解决方案3】:

我认为这取决于读取属性的位置和方式。如果您使用 vanilla java 读取这些属性,则可以通过实现 BeanFactoryPostProcessor 来注册 bean 定义。但是,如果属性本身作为 bean 出现(例如,作为 @ConfigurationProperties 的结果),我有点相信你不走运。在谷歌上搜索了一段时间后,我得出结论,唯一可靠的解决方案是重构整个设计,而不是提供多个 MyType bean,而是提供单个 MyTypeProvider bean,而后者又会有一个带有签名 List&lt;MyType&gt; getStuff() 的单一方法。然后,在您注入List&lt;MyType&gt; 的位置,改为注入List&lt;MyTypeProvider&gt;,并将getStuff 的结果合并到一个List&lt;MyType&gt; 中。同样,我知道这更像是一种解决方法,但这是迄今为止我能找到的最好的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-04-01
    • 1970-01-01
    相关资源
    最近更新 更多