BeanFactory vs FactoryBean: Key Differences in Spring
To clearly distinguish between BeanFactory and FactoryBean, the key is to understand that they have similar names but entire different roles: BeanFactory is the "top-level interface" of the IoC container, responsible for managing all beans; FactoryBean is a "factory interface" for creating complex beans, acting as a "custom creation tool" for a single bean.
1. Core Purpose (One-Sentence Distinction)
| Feature | BeanFactory | FactoryBean |
|---|---|---|
| Core Role | IoC Container (Manager) | Bean Factory (Producer) |
| Scope | Manages the lifecycle of all beans in the container | Responsible only for creating one specific bean |
| Core Methods | getBean(String name), containsBean(), etc. |
getObject() (creates the bean), getObjectType() (returns the bean type) |
| Purpose | Defines the basic behavior of the container (getting/checking beans) | Customizes the creation logic for a bean (solves complex instantiation) |
2. Detailed Breakdown
2.1 BeanFactory: The "Root Interface" of the IoC Container
BeanFactory is the lowest-level core interface of the Spring IoC container. All Spring containers (like ApplicationContext) implement this interface, which defines the fundamental capabilities of an IoC container.
Core Characteristics:
- Essence of the Container: It is not a concrete class but a "container specification"—it mandates that the container must provide capabilities like "retrieving beans, checking for beans, determining bean scope".
- Core Methods:
public interface BeanFactory {
// Retrieve a bean by name (core method)
Object getBean(String name) throws BeansException;
// Retrieve a bean by name and type
<T> T getBean(String name, Class<T> requiredType) throws BeansException;
// Check if the container contains a bean
boolean containsBean(String name);
// Check if a bean is a singleton
boolean isSingleton(String name);
}
- Common Implementations:
DefaultListableBeanFactory: The most basic container implemantation (underliesApplicationContext).ApplicationContext: ExtendsBeanFactory, an enhanced container (supports non-lazy loading, events, internationalization, etc.).
Simple Example (Using BeanFactory):
public class BeanFactoryDemo {
public static void main(String[] args) {
// Create a basic container instance
DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
// Register a simple BeanDefinition (describing UserService)
BeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition(UserService.class).getBeanDefinition();
factory.registerBeanDefinition("userService", beanDefinition);
// Get the bean from the container (core ability of BeanFactory)
UserService userService = (UserService) factory.getBean("userService");
userService.sayHello();
}
}
class UserService {
public void sayHello() {
System.out.println("Hello BeanFactory");
}
}
2.2 FactoryBean: The "Factory Interface" for Creating Complex Beans
FactoryBean is an interface provided by Spring for customizing the creation logic of a bean. When creating a bean is complex (e.g., requiring multiple initialization steps, depending on third-party resources), and using new or annotations is insufficient, you can implement FactoryBean to define the creation logic.
Core Characteristics:
- Targets a Single Bean: One
FactoryBeanis responsible for creating only one type of bean. - Core Methods:
public interface FactoryBean<T> {
// Core: Creates and returns the custom bean instance
T getObject() throws Exception;
// Returns the type of the bean created
Class<?> getObjectType();
// Whether the bean is a singleton (default is true)
default boolean isSingleton() {
return true;
}
}
- Special Retrieval Rules:
- Calling
context.getBean("factoryBeanName")returns the target bean created bygetObject(). - Calling
context.getBean("&factoryBeanName")returns theFactoryBeanitself (the&prefix is the distinguishing marker).
- Calling
Typical Usage Scenarios:
Examples include MyBatis's MapperFactoryBean when integrating with Spring, the creation of RedisTemplate in Redis clients, or the creation of database connection pools like DataSource. These all rely on FactoryBean because creating such beans involves loading configurations, initializing connections, and other complex logic.
Simple Example (Custom FactoryBean):
// 1. Define a complex bean (requires custom creation logic)
class User {
private String name;
private int age;
// Constructor + getters/setters
public User(String name, int age) {
this.name = name;
this.age = age;
}
public void introduce() {
System.out.println("Name: " + name + ", Age: " + age);
}
}
// 2. Implement FactoryBean with custom creation logic
@Component("userFactoryBean")
class UserFactoryBean implements FactoryBean<User> {
@Override
public User getObject() throws Exception {
// Simulate complex creation logic: loading config, initializing parameters, etc.
String name = "Alice";
int age = 30;
return new User(name, age); // Custom creation of User instance
}
@Override
public Class<?> getObjectType() {
return User.class; // Return the type of bean created
}
}
// 3. Test bean retrieval
public class FactoryBeanDemo {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext("com.example");
// Retrieve the target bean created by FactoryBean (User)
User user = context.getBean("userFactoryBean", User.class);
user.introduce(); // Output: Name: Alice, Age: 30
// Retrieve the FactoryBean itself (prefix with &)
UserFactoryBean factoryBean = context.getBean("&userFactoryBean", UserFactoryBean.class);
System.out.println(factoryBean.getObjectType()); // Output: class com.example.User
context.close();
}
}
3. Summary of Key Differences (Comparison Table)
| Dimension | BeanFactory | FactoryBean |
|---|---|---|
| Essence | "Interface specification" of the IoC container | "Factory interface" for creating a single bean |
| Focus | How the container manages all beans | How to create one specific bean |
| Usage | Used as a container (calling getBean()) |
Implement the interface, override getObject() to customize creation |
| Dependency | Implemented by all Spring containers | Itself is a bean, managed by BeanFactory |
| Typical Examples | ApplicationContext, DefaultListableBeanFactory |
MapperFactoryBean, RedisTemplateFactoryBean |
4. Common Points of Confusion
- Name Pitfall: Don't be misled by the order of "Factory" and "Bean".
BeanFactoryis the "factory for beans (container)", whileFactoryBeanis a "factory (which is itself a bean)". - Management Relationship: A
FactoryBeanis itself a bean, and its lifecycle is managed by theBeanFactory. TheBeanFactorycalls thegetObject()method of theFactoryBeanto create the target bean.
Conclusion
- BeanFactory is the "root interface" of the Spring IoC container, defining the core capabilities for managing beans (retrieving, checking). It is the foundation of all containers.
- FactoryBean is a "tool interface" for customizing bean creation logic, used to solve complex bean instantiation. It is itself a bean managed by the container.
- Memory Aid:
BeanFactoryis the "steward" (manages all beans), whileFactoryBeanis the "specialized craftsman" (creates only one specific bean).