Backend Development 6 min read

When to Choose BeanFactory vs ApplicationContext in Spring 5?

This article explains the core differences between Spring's BeanFactory and ApplicationContext, why ApplicationContext is generally preferred, and how to manually register BeanPostProcessors when using a plain DefaultListableBeanFactory.

Spring Full-Stack Practical Cases
Spring Full-Stack Practical Cases
Spring Full-Stack Practical Cases
When to Choose BeanFactory vs ApplicationContext in Spring 5?

Environment: Spring 5.3.10

BeanFactory

The BeanFactory API provides the foundation for Spring's IoC container. Its main contract is used for integration with other parts of Spring and third‑party frameworks. The

DefaultListableBeanFactory

implementation is a key delegate inside the higher‑level

GenericApplicationContext

container.

BeanFactory and related interfaces such as

BeanFactoryAware

,

InitializingBean

, and

DisposableBean

serve as important integration points. They work without annotations or reflection, allowing efficient interaction between the container and its components. Application‑level beans can also use these callbacks, though declarative dependency injection via annotations or configuration is more common.

Note that the core BeanFactory API does not handle configuration design or component annotations. All such functionality is introduced through extensions (e.g.,

XmlBeanDefinitionReader

,

AutowiredAnnotationBeanPostProcessor

) that operate on shared

BeanDefinition

metadata. In other words, the core BeanFactory API itself does not process annotations; extensions like

BeanPostProcessor

implement AOP and other features.

BeanFactory vs ApplicationContext

Unless you have a compelling reason, you should use

ApplicationContext

—specifically

GenericApplicationContext

and its subclass

AnnotationConfigApplicationContext

—as the common implementation for a custom startup container. These are the primary entry points of the Spring core container for loading configuration files, triggering class‑path scanning, programmatically registering bean definitions and annotated classes, and (since 5.0) registering functional bean definitions.

Because

ApplicationContext

includes all BeanFactory capabilities, it is usually recommended not to use a plain BeanFactory unless you need complete control over bean handling. In an

ApplicationContext

, special beans such as post‑processors are detected automatically by convention (by bean name or type). A plain

DefaultListableBeanFactory

is unaware of any special beans.

For features like annotation processing and AOP proxies, the

BeanPostProcessor

extension point is essential. If you use only a plain

DefaultListableBeanFactory

, these post‑processors are not detected or activated by default, which can be confusing because the bean configuration itself may be correct. You would need additional setup to fully configure the container, and annotation processing/AOP will not work unless you manually register the required post‑processors.

The following table summarizes the capabilities of BeanFactory and ApplicationContext (described in prose):

Bean instantiation: both support.

Lifecycle management: only ApplicationContext provides.

Automatic registration of

BeanPostProcessor

: only ApplicationContext.

Automatic registration of

BeanFactoryPostProcessor

: only ApplicationContext.

Convenient message source access (for i18n): only ApplicationContext.

Built‑in ApplicationEvent publishing: only ApplicationContext.

Manual Registration

To apply a

BeanPostProcessor

when using a plain

DefaultListableBeanFactory

, you must register it programmatically:

<code>DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
// populate the factory with bean definitions
factory.addBeanPostProcessor(new AutowiredAnnotationBeanPostProcessor());
factory.addBeanPostProcessor(new MyBeanPostProcessor());
// now the factory can be started
</code>

To apply a BeanFactory post‑processor, you need to invoke the appropriate methods, for example:

<code>DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(factory);
reader.loadBeanDefinitions(new FileSystemResource("beans.xml"));
// load properties
PropertySourcesPlaceholderConfigurer cfg = new PropertySourcesPlaceholderConfigurer();
cfg.setLocation(new FileSystemResource("jdbc.properties"));
cfg.postProcessBeanFactory(factory);
</code>

Both manual registration approaches are cumbersome, which explains why ApplicationContext variants are preferred in typical enterprise Spring applications, especially when relying on

BeanFactoryPostProcessor

and

BeanPostProcessor

instances to extend container functionality.

JavaBackend DevelopmentIoCSpringDependency InjectionApplicationContextBeanFactory
Spring Full-Stack Practical Cases
Written by

Spring Full-Stack Practical Cases

Full-stack Java development with Vue 2/3 front-end suite; hands-on examples and source code analysis for Spring, Spring Boot 2/3, and Spring Cloud.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.