有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java从@Configuration类中的一个方法创建多个bean

我是DI的Spring,而不是使用XML的Spring

基于配置(例如xml/properties文件),我希望创建一些特定类型的bean(具体数量由配置决定),将其放入我的上下文中,以便它们可以自动连接到类中

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

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

所以我可以这样做:

@Configuration
public MyConfigurationClass {

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

。。。但它“感觉”不对

实现这一目标的“春天”方式是什么

编辑:

想象一下这段代码,其中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();
    }
}

共 (3) 个答案

  1. # 1 楼答案

    我认为这取决于读取属性的位置和方式。如果使用vanilla java读取这些属性,那么可以通过实现BeanFactoryPostProcessor来注册bean定义。然而,如果属性本身是一个bean(例如@ConfigurationProperties的结果),我有点相信你运气不好。在谷歌搜索了一段时间后,我得出结论,唯一可靠的解决方案是重构整个设计,而不是提供多个MyType bean,而是提供单个MyTypeProvider bean,这反过来会有一个带有签名List<MyType> getStuff()的方法。然后,在你注射List<MyType>的地方,注射List<MyTypeProvider>,并将他们的getStuff结果合并成一个List<MyType>。再说一次,我知道这更像是一个解决办法,但这是迄今为止我能找到的最好的办法

  2. # 2 楼答案

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

    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_注入一个提供者)
    4. 获取一个提供者(名字“stuffB”告诉spring注入一个MyStuffImpl_B提供者)
    5. 使用提供程序创建MyStuffImpl_A的实例
    6. 使用提供程序创建MyStuffImpl_B的实例
  3. # 3 楼答案

    如果您不需要单独的限定符,并且可以按列表自动连接,那么您可以在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();
        }
    }