Add Bean Programmatically to Spring Web App Context
In Spring 3.0 you can make your bean implement BeanDefinitionRegistryPostProcessor
and add new beans via BeanDefinitionRegistry
.
In previous versions of Spring you can do the same thing in BeanFactoryPostProcessor
(though you need to cast BeanFactory
to BeanDefinitionRegistry
, which may fail).
How to add bean instance at runtime in spring WebApplicationContext?
You can make use of BeanDefinitionRegistry
(look here for API) to remove or register the beans dynamically.
So, in your SpringUtil
class, you can add the below method to remove the existing bean definition using removeBeanDefinition()
and then add a new bean definition by using registerBeanDefinition()
.
public void removeExistingAndAddNewBean(String beanId) {
AutowireCapableBeanFactory factory =
applicationContext.getAutowireCapableBeanFactory();
BeanDefinitionRegistry registry = (BeanDefinitionRegistry) factory;
registry.removeBeanDefinition(beanId);
//create newBeanObj through GenericBeanDefinition
registry.registerBeanDefinition(beanId, newBeanObj);
}
How to programatically add an @Bean definition to Spring context?
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);
}
}
Why is programmatically created bean not available in the application context
AutowireCapableBeanFactory#initializeBean(Object, String)
doesn't add a bean to a context or bean factory. The javadoc states
Initialize the given raw bean, applying factory callbacks such as
setBeanName and setBeanFactory, also applying all bean post processors
(including ones which might wrap the given raw bean).
It basically just processes the object you pass to it as if it was a bean initialized as part of the ApplicationContext
. Notice that the method returns an Object
, the result of the initialization.
Returns:
the bean instance to use, either the original or a wrapped one
Spring adding beans at runtime
See AutowireCapableBeanFactory.initializeBean(beanName).
You need to make sure the bean's not used between registration and initialization.
Also, be aware that registering singletons after the context is initialized wasn't really thread-safe until recently (4.2.2, I think). It could cause ConcurrentModificationExceptions
if other code is iterating over the beans in the factory.
However, in this case, it might be too late to get the HTTP paths registered, you might need more code to do that.
retrieve Bean programmatically
Here an Example
public class MyFancyBean implements ApplicationContextAware {
private ApplicationContext applicationContext;
void setApplicationContext(ApplicationContext applicationContext) {
this.applicationContext = applicationContext;
}
public void businessMethod() {
//use applicationContext somehow
}
}
However you rarely need to access ApplicationContext directly. Typically you start it once and let beans populate themselves automatically.
Here you go:
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
Note that you don't have to mention files already included in applicationContext.xml. Now you can simply fetch one bean by name or type:
ctx.getBean("someName")
Note that there are tons of ways to start Spring - using ContextLoaderListener, @Configuration class, etc.
Related Topics
Closing Jdbc Connections in Pool
How to Create an Array of Arraylists
How to Use the Instanceof Operator in a Switch Statement
How to View the SQL Queries Issued by JPA
How to Create Immutable Objects in Java
Using Bigdecimal to Work with Currencies
When Overriding a Method, Why How to Increase Access But Not Decrease It
Spring: How to Inject an Httpservletrequest into a Request-Scoped Bean
Spring Boot - Cannot Determine Embedded Database Driver Class for Database Type None
Integer.Tostring(Int I) VS String.Valueof(Int I)
Fuzzy String Search Library in Java
Before and After Suite Execution Hook in Junit 4.X
How to Select a Dropdown Value in Selenium Webdriver Using Java
Why Won't This Generic Java Code Compile