Reputation: 86627
Normally I'm adding my objects to spring context using @Bean
definition:
@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 create the bean name dynamically 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 an NPE as the autowired dependecies are not yet initialized here!
So, how can I add those beans programatically?
Upvotes: 4
Views: 7162
Reputation: 23226
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");
}
}
Upvotes: 1
Reputation: 2230
You should autowire the bean factory, and use a @PostConstruct
to register your bean. That way, you guarantee that all dependencies has been injected (the bean factory is injected by the container, no setup is needed).
@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);
}
}
Upvotes: 4
Reputation: 3326
You should put this before:
beanFactory.autowireBean(port);
But, if you want to initialize a bean, I think that you want to create a single instance (I'm saying this because in the example, you used the @Bean
annotation):
beanFactory.initializeBean(port, "myDynamicPortName");
instead of a singleton one:
beanFactory.registerSingleton("myDynamicPortName", port);
Upvotes: 4