This is done by accessing the ApplicationContext's BeanFactory through the getBeanFactory() method, which returns the BeanFactory DefaultListableBeanFactory implementation. DefaultListableBeanFactory supports this registration through the registerSingleton(..) and registerBeanDefinition(..) methods.
The BeanFactory is the actual container which instantiates, configures, and manages a number of beans. These beans typically collaborate with one another, and thus have dependencies between themselves.
context. ApplicationContext represents the Spring IoC container and is responsible for instantiating, configuring, and assembling the aforementioned beans. The container gets its instructions on what objects to instantiate, configure, and assemble by reading configuration metadata.
The BeanFactory by default lazy loads the beans, it creates the bean only when the getBean() method is called. whereas ApplicationContext preloads all the singleton beans upon start-up.
The spring docs are great on this: 3.8.1. BeanFactory or ApplicationContext?. They have a table with a comparison, I'll post a snippet:
Bean Factory
Application Context
So if you need any of the points presented on the Application Context side, you should use ApplicationContext.
Spring provides two kinds of IOC container, one is
XMLBeanFactory
and other isApplicationContext
.
BeanFactory | ApplicationContext | |
---|---|---|
Annotation support | No | Yes |
BeanPostProcessor Registration | Manual | Automatic |
Implementation | XMLBeanFactory | ClassPath/FileSystem/WebXmlApplicationContext |
Internationalization | No | Yes |
Enterprise services | No | Yes |
ApplicationEvent publication | No | Yes |
FileSystemXmlApplicationContext
Beans loaded through the full path.ClassPathXmlApplicationContext
Beans loaded through the CLASSPATHXMLWebApplicationContext
and AnnotationConfigWebApplicationContext
beans loaded through the web application context.AnnotationConfigApplicationContext
Loading Spring beans from Annotation based configuration.example:
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(BeansConfiguration.class);
ApplicationContext
is the container initialized by a ContextLoaderListener
or ContextLoaderServlet
defined in a web.xml
and ContextLoaderPlugin
defined in struts-config.xml
.Note: XmlBeanFactory
is deprecated as of Spring 3.1 in favor of DefaultListableBeanFactory
and XmlBeanDefinitionReader
.
To me, the primary difference to choose BeanFactory
over ApplicationContext
seems to be that ApplicationContext
will pre-instantiate all of the beans. From the Spring docs:
Spring sets properties and resolves dependencies as late as possible, when the bean is actually created. This means that a Spring container which has loaded correctly can later generate an exception when you request an object if there is a problem creating that object or one of its dependencies. For example, the bean throws an exception as a result of a missing or invalid property. This potentially delayed visibility of some configuration issues is why ApplicationContext implementations by default pre-instantiate singleton beans. At the cost of some upfront time and memory to create these beans before they are actually needed, you discover configuration issues when the ApplicationContext is created, not later. You can still override this default behavior so that singleton beans will lazy-initialize, rather than be pre-instantiated.
Given this, I initially chose BeanFactory
for use in integration/performance tests since I didn't want to load the entire application for testing isolated beans. However -- and somebody correct me if I'm wrong -- BeanFactory
doesn't support classpath
XML configuration. So BeanFactory
and ApplicationContext
each provide a crucial feature I wanted, but neither did both.
Near as I can tell, the note in the documentation about overriding default instantiation behavior takes place in the configuration, and it's per-bean, so I can't just set the "lazy-init" attribute in the XML file or I'm stuck maintaining a version of it for test and one for deployment.
What I ended up doing was extending ClassPathXmlApplicationContext
to lazily load beans for use in tests like so:
public class LazyLoadingXmlApplicationContext extends ClassPathXmlApplicationContext {
public LazyLoadingXmlApplicationContext(String[] configLocations) {
super(configLocations);
}
/**
* Upon loading bean definitions, force beans to be lazy-initialized.
* @see org.springframework.context.support.AbstractXmlApplicationContext#loadBeanDefinitions(org.springframework.beans.factory.xml.XmlBeanDefinitionReader)
*/
@Override
protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws IOException {
super.loadBeanDefinitions(reader);
for (String name: reader.getBeanFactory().getBeanDefinitionNames()) {
AbstractBeanDefinition beanDefinition = (AbstractBeanDefinition) reader.getBeanFactory().getBeanDefinition(name);
beanDefinition.setLazyInit(true);
}
}
}
To add onto what Miguel Ping answered, here is another section from the documentation that answers this as well:
Short version: use an ApplicationContext unless you have a really good reason for not doing so. For those of you that are looking for slightly more depth as to the 'but why' of the above recommendation, keep reading.
(posting this for any future Spring novices who might read this question)
ApplicationContext
is more preferred way than BeanFactory
In new Spring versions BeanFactory
is replaced with ApplicationContext
. But still BeanFactory
exists for backward compatability
ApplicationContext extends BeanFactory
and has the following benefits
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With