简体   繁体   中英

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.

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)

You are probably missing @DependsOn somewhere in your code. Since you are creating beans programmatically there's no guarantee when those beans are going to be available in application context. To enforce order, you can add @DependsOn to a configuration that uses it. See Example below

Configuration that depends on other configuration that creates beans programatically

@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

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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