BeanFactory vs ApplicationContext

Viewed 287931

I'm pretty new to the Spring Framework, I've been playing around with it and putting a few samples apps together for the purposes of evaluating Spring MVC for use in an upcoming company project. So far I really like what I see in Spring MVC, seems very easy to use and encourages you to write classes that are very unit test-friendly.

Just as an exercise, I'm writing a main method for one of my sample/test projects. One thing I'm unclear about is the exact differences between BeanFactory and ApplicationContext - which is appropriate to use in which conditions?

I understand that ApplicationContext extends BeanFactory, but if I'm just writing a simple main method, do I need the extra functionality that ApplicationContext provides? And just exactly what kind of extra functionality does ApplicationContext provide?

In addition to answering "which should I use in a main() method", are there any standards or guidelines as far as which implementation I should use in such a scenario? Should my main() method be written to depend on the bean/application configuration to be in XML format - is that a safe assumption, or am I locking the user into something specific?

And does this answer change in a web environment - if any of my classes needed to be aware of Spring, are they more likely to need ApplicationContext?

Thanks for any help. I know a lot of these questions are probably answered in the reference manual, but I'm having a hard time finding a clear breakdown of these two interfaces and the pros/cons of each without reading thru the manual with a fine-tooth comb.

22 Answers

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

  • Bean instantiation/wiring

Application Context

  • Bean instantiation/wiring
  • Automatic BeanPostProcessor registration
  • Automatic BeanFactoryPostProcessor registration
  • Convenient MessageSource access (for i18n)
  • ApplicationEvent publication

So if you need any of the points presented on the Application Context side, you should use ApplicationContext.

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)

  1. ApplicationContext is more preferred way than BeanFactory

  2. In new Spring versions BeanFactory is replaced with ApplicationContext. But still BeanFactory exists for backward compatability

  3. ApplicationContext extends BeanFactory and has the following benefits
    • it supports internationalization for text messages
    • it supports event publication to the registered listeners
    • access to the resources such as URLs and files

I think it's better to always use ApplicationContext, unless you're in a mobile environment like someone else said already. ApplicationContext has more functionality and you definitely want to use the PostProcessors such as RequiredAnnotationBeanPostProcessor, AutowiredAnnotationBeanPostProcessor and CommonAnnotationBeanPostProcessor, which will help you simplify your Spring configuration files, and you can use annotations such as @Required, @PostConstruct, @Resource, etc in your beans.

Even if you don't use all the stuff ApplicationContext offers, it's better to use it anyway, and then later if you decide to use some resource stuff such as messages or post processors, or the other schema to add transactional advices and such, you will already have an ApplicationContext and won't need to change any code.

If you're writing a standalone app, load the ApplicationContext in your main method, using a ClassPathXmlApplicationContext, and get the main bean and invoke its run() (or whatever method) to start your app. If you're writing a web app, use the ContextLoaderListener in web.xml so that it creates the ApplicationContext and you can later get it from the ServletContext, regardless of whether you're using JSP, JSF, JSTL, struts, Tapestry, etc.

Also, remember you can use multiple Spring configuration files and you can either create the ApplicationContext by listing all the files in the constructor (or listing them in the context-param for the ContextLoaderListener), or you can just load a main config file which has import statements. You can import a Spring configuration file into another Spring configuration file by using <import resource="otherfile.xml" /> which is very useful when you programmatically create the ApplicationContext in the main method and load only one Spring config file.

Difference between BeanFactory and ApplicationContext are following:

  1. BeanFactory uses lazy initialization but ApplicationContext uses eager initialization. In case of BeanFactory, bean is created when you call getBeans() method, but bean is created upfront in case of ApplicationContext when the ApplicationContext object is created.
  2. BeanFactory explicitly provide a resource object using syntax but ApplicationContext creates and manages resource objects on its own.
  3. BeanFactory doesnt support internatiolization but ApplicationContext supports internationalization.
  4. With BeanFactory annotation based dependency injection is not supported but annotation based dependency injection is supported in ApplicationContext.

Using BeanFactory:

BeanFactory beanfactory = new XMLBeanFactory(new FileSystemResource("spring.xml"));
 Triangle triangle =(Triangle)beanFactory.getBean("triangle");

Using ApplicationContext:

ApplicationContext context = new ClassPathXMLApplicationContext("spring.xml")
Triangle triangle =(Triangle)context.getBean("triangle");

For the most part, ApplicationContext is preferred unless you need to save resources, like on a mobile application.

I'm not sure about depending on XML format, but I'm pretty sure the most common implementations of ApplicationContext are the XML ones such as ClassPathXmlApplicationContext, XmlWebApplicationContext, and FileSystemXmlApplicationContext. Those are the only three I've ever used.

If your developing a web app, it's safe to say you'll need to use XmlWebApplicationContext.

If you want your beans to be aware of Spring, you can have them implement BeanFactoryAware and/or ApplicationContextAware for that, so you can use either BeanFactory or ApplicationContext and choose which interface to implement.

I need to explain the BeanFactory & ApplicationContext.

BeanFactory: BeanFactory is root interface for accessing the SpringBean Container.There is basic client view of a bean container. That interface is implemented by the object class that holds the number of beans definitions, and each uniquely identify by the String name
Depending the Bean definition the factory will return the instance that instance may be the instance of contained object or a single shared instance. Which type of instance will be return depends of bean factory configuration.
Normally Bean factory will load the all the all the beans definition, which stored in the configuration source like XML...etc.

BeanFactory is a simplest container providing the basic support for Dependency Injection

Application Context Application context is a central interface with in the spring application that provide the configuration information to the application. It implements the Bean Factory Interface.

Application context is an advance container its add advance level of enterprise specific functionality such as ability to resolve the textual message from the property file....etc

An ApplicationContext provides:

Bean factory methods for accessing application components. Inherited from ListableBeanFactory. The ability to load file resources in a generic fashion. Inherited from the ResourceLoader interface. The ability to publish events to registered listeners. Inherited from the ApplicationEventPublisher interface. The ability to resolve messages, supporting internationalization. Inherited from the MessageSource interface. Inheritance from a parent context. Definitions in a descendant context will always take priority. This means, for example, that a single parent context can be used by an entire web application, while each servlet has its own child context that is independent of that of any other servlet. In addition to standard BeanFactory lifecycle capabilities, ApplicationContext implementations detect and invoke ApplicationContextAware beans as well as ResourceLoaderAware, ApplicationEventPublisherAware and MessageSourceAware beans.

My six cents:

  1. BeanFactory and ApplicationContext both are interfaces where ApplicationContext extends BeanFactory. So ApplicationContext is a child interface and BeanFactory is the parent interface. In other words, ApplicationContext has all the features of BeanFactory and it has some additional features that are not present in BeanFactory.
  2. BeanFactory loads beans on-demand that is Lazy Loading whereas ApplicationContext loads all beans at startup that is Eager Loading.
  3. BeanFactory does not support annotations whereas ApplicationContext supports annotations.
  4. ApplicationContext has additional features that are not present in BeanFactory: Internationalization, Event Publishing, AOP features.
  5. BeanFactory only supports two scopes — Singleton and Prototype whereas ApplicationContext supports all bean scopes.
  6. BeanFactory does not register BeanFactoryPostProcessor and BeanPostProcessor automatically whereas ApplicationContext automatically registers them.

I think it is worth mentioning that since Spring 3, if you want to create a factory, you can also use the @configuration annotation combined with the proper @scope

@Configuration
public class MyFactory {

    @Bean
    @Scope("prototype")
    public MyClass create() {
        return new MyClass();
    }
}

Your factory should be visible by Spring container using the @ComponentScan annotation or xml configuration

Spring bean scopes article from baeldung site

do use BeanFactory for non-web applications because it supports only Singleton and Prototype bean-scopes.

While ApplicationContext container does support all the bean-scopes so you should use it for web applications.

In summary:

The ApplicationContext includes all functionality of the BeanFactory. It is generally recommended to use the former.

There are some limited situations such as in a Mobile application, where memory consumption might be critical.

In that scenarios, It can be justifiable to use the more lightweight BeanFactory. However, in the most enterprise applications, the ApplicationContext is what you will want to use.

For more, see my blog post:

Difference between BeanFactory and ApplicationContext in Spring – The java spring blog from the basics

The BeanFactory means spring container which lazily instantiates bean objects after getBean() method is invoked at runtime.

The ApplicationContext means spring framework which eagerly instantiates bean objects during deployment time without or before invoking getBean() method at runtime.

Related