简体   繁体   English

Spring:如何在 Spring 中创建类似的 bean 动态启动?

[英]Spring : How to create similar beans in Spring Boot dynamically?

I want to create multiple similar beans dynamically based on the properties file to replace the duplicate code.我想根据属性文件动态创建多个相似的bean来替换重复的代码。

Is that a good idea?这是一个好主意吗?

My original duplicate code:我原来的重复代码:

@Configuration
@Order(Integer.MIN_VALUE)
public class HessianFactory {


    public static PubHessianServiceExporter createHessianService(Object service, Class clazz) {
        PubHessianServiceExporter exporter = new PubHessianServiceExporter();
        exporter.setService(service);
        exporter.setServiceInterface(clazz);
        return exporter;
    }

    @Bean("/svc/curriculumScheduleService/1")
    public PubHessianServiceExporter curriculumScheduleService1() {
        return HessianFactory.createHessianService(StudentAppServiceFactory.curriculumScheduleServices.get(1), CurriculumScheduleService.class);
    }

    @Bean("/svc/curriculumScheduleService/2")
    public PubHessianServiceExporter curriculumScheduleService2() {
        return HessianFactory.createHessianService(StudentAppServiceFactory.curriculumScheduleServices.get(2), CurriculumScheduleService.class);
    }

    @Bean("/svc/curriculumScheduleService/3")
    public PubHessianServiceExporter curriculumScheduleService3() {
        return HessianFactory.createHessianService(StudentAppServiceFactory.curriculumScheduleServices.get(3), CurriculumScheduleService.class);
    }

    @Bean("/svc/curriculumScheduleService/5")
    public PubHessianServiceExporter curriculumScheduleService5() {
        return HessianFactory.createHessianService(StudentAppServiceFactory.curriculumScheduleServices.get(5), CurriculumScheduleService.class);
    }
}

I have tried with the code given below:我尝试过使用下面给出的代码:

@Configuration
@Order(Integer.MIN_VALUE)
public class HessianFactory {

    @Value("${sign-sys-ids}")
    private String[] signSysIds;
    @Autowired
    private ConfigurableBeanFactory beanFactory;


    public static HessianServiceExporter createHessianService(Object service, Class clazz) {
        HessianServiceExporter exporter = new HessianServiceExporter();
        exporter.setService(service);
        exporter.setServiceInterface(clazz);
        return exporter;
    }

    @PostConstruct
    public void init() throws BeansException {
        Arrays.stream(signSysIds).forEach(
            i -> {
                HessianServiceExporter hessianServiceExporter = createHessianService(
                    StudentAppServiceFactory.curriculumScheduleServices.get(Integer.parseInt(i)), CurriculumScheduleService.class);
                beanFactory.registerSingleton("/svc/curriculumScheduleService/" + i, hessianServiceExporter);
            }
        );
    }
}

But the above code is not working.但是上面的代码不起作用。

curriculumScheduleServices is map of curriculumScheduleService with different index(i) courseScheduleServices是具有不同index(i)的课程计划服务的 map

You are probably missing @DependsOn somewhere in your code.您可能在代码中的某处缺少@DependsOn Since you are creating beans programmatically there's no guarantee when those beans are going to be available in application context.由于您以编程方式创建 bean,因此无法保证这些 bean 何时在应用程序上下文中可用。 To enforce order, you can add @DependsOn to a configuration that uses it.要强制执行顺序,您可以将@DependsOn添加到使用它的配置中。 See Example below请参阅下面的示例

Configuration that depends on other configuration that creates beans programatically依赖于以编程方式创建 bean 的其他配置的配置

@Configuration
@DependsOn("TestConfiguration2")
public class TestConfiguration1 {

  @Autowired
  @Qualifier("/svc/curriculumScheduleService/1")
  private DummyClass dummyClass1;
  @Autowired
  @Qualifier("/svc/curriculumScheduleService/2")
  private DummyClass dummyClass2;
  @Autowired
  @Qualifier("/svc/curriculumScheduleService/3")
  private DummyClass dummyClass3;
  @Autowired
  @Qualifier("/svc/curriculumScheduleService/5")
  private DummyClass dummyClass5;

  @PostConstruct
  public void printBeans() {
    System.out.println(dummyClass1.getVal());
    System.out.println(dummyClass2.getVal());
    System.out.println(dummyClass3.getVal());
    System.out.println(dummyClass5.getVal());
  }
}

Configuration that creates beans programatically以编程方式创建 bean 的配置

@Configuration("TestConfiguration2")
public class TestConfiguration2 {

  @Autowired
  private ConfigurableBeanFactory beanFactory;

  @PostConstruct
  public void setup() {
    String[] array = {"1", "2", "3", "5"};
    Arrays.stream(array).map(Integer::parseInt).forEach(i -> {
      System.out.println("creating new bean");
      beanFactory.registerSingleton("/svc/curriculumScheduleService/" + i, new DummyClass(i));
    });
  }
}
@PostConstruct
public void init() throws BeansException {
    Arrays.stream(signSysIds).forEach(
        i -> {
            String beanName = "/svc/curriculumScheduleService/" + i;
            AbstractBeanDefinition bean = BeanDefinitionBuilder.genericBeanDefinition(PubHessianServiceExporter.class)
                .addPropertyValue("service", StudentAppServiceFactory.curriculumScheduleServices.get(Integer.parseInt(i)))
                .addPropertyValue("serviceInterface", CurriculumScheduleService.class)
                .getBeanDefinition();
            beanFactory.registerBeanDefinition(beanName, bean);
        }
    );
}

it work.这行得通。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM