How do I programmatically add a @Bean definition to a Spring context?

I usually add my objects to spring context using the definition @Bean

:

@Autowired
private SpringBus bus;

//register a singleton
@Bean
public WebservicePort getPort() {
    //new port()
    //initialize
    //configure
    //return port;
}

      

But now I need deeper control of the process, especially I want to dynamically create the bean name under which the bean is registered.

I tried:

@Service
public class MyPortRegistrar implements BeanDefinitionRegistryPostProcessor {

        @Autowired
        private SpringBus bus;

        @Override
        public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
            System.out.println(bus); //prints null

            //create and configure port with the SpringBus
            Port port = new WebservicePort(bus); // -> throws NullPointerException
            beanFactory.autowireBean(port);
            beanFactory.initializeBean(port, "myDynamicPortName");  
        }
}

      

But this throws out the NPE since already authorized dependencies are not initialized here.

So how can I add these beans programmatically?

+3


source to share


3 answers


You have to autwire bean factory and use @PostConstruct

bean to register. This way you ensure that all dependencies have been injected (the bean factory is injected by the container, no setup required).



@Service
public class MyPortRegistrar {

    @Autowired
    private ConfigurableBeanFactory beanFactory;

    @Autowired
    private SpringBus bus;

    @PostConstruct
    public void createPort() {
        Port port = new WebservicePort(bus);
        beanFactory.registerSingleton("myDynamicPortName", port);
    }
}

      

+1


source


You have to put this before:

beanFactory.autowireBean(port);

      

But if you want to initialize the bean, I think you want to create one instance (I say this because you used annotation in the example @Bean

):



beanFactory.initializeBean(port, "myDynamicPortName");  

      

instead of singleton:

beanFactory.registerSingleton("myDynamicPortName", port);

      

+4


source


An alternative to Khalid's answer (which I think requires some additional dependencies and configuration) is to implement the InitializingBean interface:

@Service
public class MyPortRegistrar implements InitializingBean {

    @Autowired
    private SpringBus bus;

    @Autowired
    private ConfigurableBeanFactory beanFactory;

    @Override
    public void afterPropertiesSet() throws Exception
        System.out.println(bus); //prints null

        //create and configure port with the SpringBus
        Port port = new WebservicePort(bus); // -> throws NullPointerException
        beanFactory.autowireBean(port);
        beanFactory.initializeBean(port, "myDynamicPortName");  
    }
}

      

+1


source







All Articles