
Spring FactoryBean: A Guide for Developers
Introduction
A Spring FactoryBean
is a special kind of bean that acts as a factory for creating other beans. The Spring Framework is one of the most popular Java frameworks for the development of enterprise applications. It offers extensive support for Dependency Injection (DI) and Bean Lifecycle Management, making it easier for developers to create scalable and maintainable applications. One of the powerful but lesser-known features of the Spring bean management system is the FactoryBean
interface.
When we work with Spring, we usually define beans using annotations (@Component
, @Service
, @Repository
, etc.) or through Java and XML configuration. However, there are cases where we need a more flexible and controlled way to create beans — this is where FactoryBean
comes into play.
Instead of defining a bean directly, we define a FactoryBean
that produces and manages the creation of a bean. This approach is particularly useful when working with complex objects, expensive resources or objects that require special initialization logic.
What you will learn in this post
In this blog post, we will explore the following:
What FactoryBean
is and how it works.
Why and when to use a FactoryBean
in Spring applications.
How to implement your own FactoryBean
with examples.
Differences between FactoryBean
and Factory Method.
Some of the most commonly used built-in FactoryBeans in Spring.
Best practices and common pitfalls to avoid when using FactoryBean
.
By the end of this post, you’ll have a solid understanding of how FactoryBean
works and how to use it effectively in your Spring applications. Let’s dive in!
What is a FactoryBean in Spring?
In a typical Spring application, we define beans using configuration files (XML or Java based) and let the Spring container manage their instantiation, dependencies and lifecycle. However, there are cases where creating a bean requires additional logic, such as:
- Constructing a complex object that depends on external configurations.
- Wrapping a third-party library that does not integrate smoothly with Spring’s dependency injection.
- Implementation of proxy objects for AOP (Aspect-Oriented Programming) or transaction management.
This is where FactoryBean
comes into play.
Definition of FactoryBean
A FactoryBean
is a special Spring bean that serves as a factory for creating objects. Instead of being a normal bean instance, it produces another object (the target bean) and provides Spring with a way to manage its lifecycle.
Unlike normal beans, where Spring instantiates the class directly, a FactoryBean
allows developers to control how an object is created and initialized. This is particularly useful when an object cannot simply be created with the new
keyword or requires special post-processing.
How does FactoryBean work?
Spring treats beans that implement FactoryBean
differently from normal beans. When a FactoryBean
is defined in the Spring container, it does not expose itself as a bean. Instead, it exposes the object it creates.
Key concept:
- A FactoryBean is itself a bean, but it is not the object that is injected into dependent beans.
- Spring calls the
getObject()
method on theFactoryBean
to get the actual object it is supposed to manage. - The resulting object can be a Singleton (shared instance) or a Prototype (new instance per request) depending on the configuration.
Core methods of FactoryBean
To implement a FactoryBean
, you need to override three important methods:
method | purpose |
---|---|
T getObject() | Creates the bean instance to be published and returns it. |
Class getObjectType() | Returns the type of the object created by this factory. |
boolean isSingleton() | Specifies whether the created object should be a singleton or a prototype. |
Example: A simple FactoryBean implementation
import org.springframework.beans.factory.FactoryBean;
public class MyFactoryBean implements FactoryBean {
@Override
public MyService getObject() throws Exception {
return new MyService(); // Custom object creation logic
}
@Override
public Class getObjectType() {
return MyService.class;
}
@Override
public boolean isSingleton() {
return true; // Return false for the prototype scope
}
}
Here MyFactoryBean
implements the FactoryBean
, which means that it creates an instance of MyService
.
The most important findings
FactoryBean
is a special kind of Spring Bean that creates and manages another Bean.- It provides a way to customize object instantiation within the Spring container.
- The Spring container calls
getObject()
to get the actual bean instance. - You can control whether the bean is a Singleton or a Prototype by overriding
isSingleton()
.
In the next section, we will look at why you need a FactoryBean
and what use cases there are.
Why use a FactoryBean?
The FactoryBean mechanism in Spring is useful when the instantiation of beans requires additional control beyond the typical constructor or setter-based injection. Although most beans in Spring applications are defined with a simple class instantiation, there are cases where the standard approach is not sufficient.
Let’s look at the main reasons why you need a FactoryBean
and when it is preferable to direct bean creation.
Common use cases for FactoryBean
Creating complex objects
Some objects need to be set up additionally after instantiation. A FactoryBean
allows you to encapsulate the complexity of object creation and keep the configuration clean at the same time.
Example: Suppose you need to create a database connection object that needs to read credentials from an external service before initialization.
public class DataSourceFactoryBean implements FactoryBean {
@Override
public DataSource getObject() throws Exception {
String url = fetchDatabaseUrl(); // Fetch URL dynamically
String user = fetchUser(); // Fetch credentials
String password = fetchPassword();
return new DataSource(url, user, password);
}
@Override
public Class getObjectType() {
return DataSource.class;
}
@Override
public boolean isSingleton() {
return true;
}
}
Here, the factory ensures that the DataSource
object is fully initialized before it is injected into dependent beans.
Wrapping of third-party libraries
Sometimes third-party libraries do not follow the Spring pattern for instantiating beans, which makes direct integration difficult. A FactoryBean
can close the gap by taking over their setup.
Example: You need to integrate an encryption library that requires a factory to initialize encryption keys.
public class EncryptionServiceFactoryBean implements FactoryBean {
@Override
public EncryptionService getObject() {
EncryptionService encryptionService = new EncryptionService();
encryptionService.initializeKeys(); // Custom setup
return encryptionService;
}
@Override
public Class getObjectType() {
return EncryptionService.class;
}
@Override
public boolean isSingleton() {
return true;
}
}
This ensures that the EncryptionService
is created correctly and can be used in the Spring context.
Implementation of proxies for AOP and transactions
Spring relies heavily on dynamic proxies to enable Aspect-Oriented Programming (AOP), transaction management and security features. the FactoryBean` plays an important role in the creation of proxy objects.
Example: Spring’s ProxyFactoryBean
creates proxy objects for method-level security.
<bean id="transactionProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="target" ref="myService"/>
<property name="interceptorNames">
<list>
<value>transactionInterceptor</value>
</list>
</property>
</bean>
This FactoryBean
dynamically creates a proxy for myService
and applies transaction management in the background.
Manage expensive resource creation
Some objects are expensive to create, e.g. database connections, thread pools or caches. A FactoryBean
can manage their lifecycle efficiently.
Example: If an expensive calculation is needed when initializing a bean, a FactoryBean
ensures that it is only executed when needed.
public class ExpensiveResourceFactoryBean implements FactoryBean {
private ExpensiveResource instance;
@Override
public ExpensiveResource getObject() {
if (instance == null) {
instance = new ExpensiveResource();
instance.initialize(); // Simulating an expensive setup
}
return instance;
}
@Override
public Class getObjectType() {
return ExpensiveResource.class;
}
@Override
public boolean isSingleton() {
return true;
}
}
This ensures that the ExpensiveResource
is only created once and reused.
Advantages of the FactoryBean
Encapsulation of the creation of complex objects: The configuration remains clean and modular.
Better control over bean instantiation: You can initialize objects dynamically instead of relying on direct constructor calls.
Performance optimization: Helps to efficiently manage the creation of expensive objects.
Seamless third-party integration: Integrates external libraries that are not Spring-friendly.
Improved AOP and proxying support: Facilitates Spring internal mechanisms such as transaction management and security.
When should you not use a FactoryBean?
While FactoryBean
is powerful, it is not always necessary. You should not use it if:
The object can be instantiated directly with a simple new
call.
No additional setup or special initialization is required.
Spring already provides built-in support for the required functionality (e.g. the @Bean
configuration for simple objects).
Implementation of a simple FactoryBean
Now that we know what a FactoryBean
is and why it is useful, let’s go through the implementation step by step. In this section we will:
- Create a custom
FactoryBean
. - Register it in the Spring container.
- Retrieve and use the bean created by the factory.
Example use case
Suppose we need to create an instance of the DatabaseConnection class. The connection data (e.g. URL, username and password) may need to be retrieved from an external source (e.g. a configuration file or an environment variable). Instead of instantiating the DatabaseConnection
class manually, we can delegate this task to a FactoryBean
.
Creating the DatabaseConnection Class
First, let’s define a simple class that represents a database connection:
public class DatabaseConnection {
private String url;
private String username;
private String password;
public DatabaseConnection(String url, String username, String password) {
this.url = url;
this.username = username;
this.password = password;
}
public void connect() {
System.out.println("Connect to the database at " + url + " with user " + username);
}
}
This class requires certain parameters (url
, username
and password
) during instantiation.
Creating the FactoryBean
Next, we create a custom FactoryBean
that will be responsible for creating DatabaseConnection
objects.
import org.springframework.beans.factory.FactoryBean;
public class DatabaseConnectionFactoryBean implements FactoryBean {
private String url;
private String username;
private String password;
// Setter for dependency injection
public void setUrl(String url) {
this.url = url;
}
public void setUsername(String username) {
this.username = username;
}
public void setPassword(String password) {
this.password = password;
}
@Override
public DatabaseConnection getObject() {
return new DatabaseConnection(url, username, password);
}
@Override
public Class getObjectType() {
return DatabaseConnection.class;
}
@Override
public boolean isSingleton() {
return true; // Return false for prototype instances
}
}
Explanation:
- The
DatabaseConnectionFactoryBean
implements theFactoryBean
. - It defines the required properties (
url
,username
,password
), which can be injected via setters. - The
getObject()
method creates an instance ofDatabaseConnection
and returns it. - The method
getObjectType()
tells Spring that this factory creates objects of the typeDatabaseConnection
. - The
isSingleton()
method specifies whether the object should be a singleton (shared instance) or a prototype (new instance per request).
Registration of the FactoryBean in Spring
Now that we have our factory, we need to register it in the Spring container. We can do this with the XML-based configuration or the Java-based configuration.
XML-based configuration
<bean id="databaseConnectionFactory" class="com.example.DatabaseConnectionFactoryBean">
<property name="url" value="jdbc:mysql://localhost:3306/mydb"/>
<property name="username" value="admin"/>
<property name="password" value="secret"/>
</bean>
<bean id="databaseConnection" factory-bean="databaseConnectionFactory" factory-method="getObject"/>
Here:
databaseConnectionFactory
is the actualFactoryBean
.databaseConnection
is the bean created by the factory (which is retrieved usinggetObject()
).
Java-based configuration (Spring @Configuration Class)
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration public class AppConfig {
@Bean
public DatabaseConnectionFactoryBean databaseConnectionFactory() {
DatabaseConnectionFactoryBean factoryBean = new DatabaseConnectionFactoryBean();
factoryBean.setUrl("jdbc:mysql://localhost:3306/mydb");
factoryBean.setUsername("admin");
factoryBean.setPassword("secret");
return factoryBean;
}
@Bean
public DatabaseConnection databaseConnection(DatabaseConnectionFactoryBean factoryBean) throws Exception {
return factoryBean.getObject();
}
}
- The
databaseConnectionFactory()
method registers theDatabaseConnectionFactoryBean
as a bean. - The method
DatabaseConnection()
retrieves the current instance ofDatabaseConnection
.
Retrieving the bean from the Spring context
Once the factory bean is registered, we can retrieve the DatabaseConnection
object from the Spring context.
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class Main {
public static void main(String[] args) throws Exception {
ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
DatabaseConnection connection = context.getBean(DatabaseConnection.class);
connection.connect(); // Output: Connection to the database at jdbc:mysql://localhost:3306/mydb with user admin
}
}
Spring automatically calls getObject()
on FactoryBean
so that DatabaseConnection
is injected into the dependent beans instead of DatabaseConnectionFactoryBean
.
Retrieving the FactoryBean itself
What if we need to retrieve the actual FactoryBean
instead of the object it creates?
Spring offers a special way to do this:
DatabaseConnectionFactoryBean factoryBean = (DatabaseConnectionFactoryBean) context.getBean("&databaseConnectionFactory");
- Adding “&” in front of the bean name tells Spring to return the
FactoryBean
itself and not the object it creates. - This is useful when we need to dynamically check or change the behavior of the factory.
FactoryBean vs. Factory Method: Main differences
When working with Spring, we often hear about two different ways to dynamically create and manage objects:
- FactoryBean (a special Spring interface that provides custom bean creation logic).
- FactoryMethod (a static or instance method that returns an object and is typically used in
@Bean
definitions).
Although both approaches allow for customization of object creation, they are fundamentally different in the way they integrate with Spring’s bean management system.
In this section, we will explore the key differences between these two approaches and when one is preferable to the other.
What is a factory method?
A factory method is simply a method that returns an instance of a class, usually within a Spring configuration class (@Configuration
). It can be:
Static – It is called on a class without requiring an instance.
Instance-based – Called for an existing object.
Example: Static factory method in Java
public class CarFactory {
public static CreateCar() {
return new Car("Tesla", "Model S");
}
}
Here, the createCar()
method acts as a static factory method that returns a Car
object.
Example: Using the factory method in the Spring Java configuration
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration public class AppConfig {
@Bean
public Car car() {
return CarFactory.createCar(); // Using static factory method
}
}
- The
car()
method functions as a factory method and is registered as a Spring bean. - Whenever Spring needs a
Car
bean, it callsCarFactory.createCar()
to create an instance.
What happens here?
- Spring calls the factory method once during the initialization of the bean.
- The factory method delivers the actual object (
Car
), which is then managed as a Spring bean.
What is a FactoryBean?
A FactoryBean is a Spring-specific interface that provides extended control over object creation. Instead of returning the object directly (like a factory method), a FactoryBean
:
- Implements
FactoryBean
to define its own instantiation logic. - Is itself a Spring bean, but represents another bean (the one it creates).
- Uses Spring’s lifecycle management and supports singleton/prototype scope, lazy initialization, etc.
Example: FactoryBean for Car
import org.springframework.beans.factory.FactoryBean;
public class CarFactoryBean implements FactoryBean {
@Override
public Car getObject() {
return new Car("Tesla", "Model S");
}
@Override
public Class getObjectType() {
return Car.class;
}
@Override
public boolean isSingleton() {
return true;
}
}
- Instead of defining a factory method, we implement the
FactoryBean
interface. - Spring will call
getObject()
to get the actualCar
instance.
Registration of the FactoryBean in the Java configuration
@Configuration public class AppConfig {
@Bean
public CarFactoryBean carFactoryBean() {
return new CarFactoryBean();
}
@Bean
public Car car(CarFactoryBean factoryBean) throws Exception {
return factoryBean.getObject(); // Retrieve the created object
}
}
Main differences between FactoryBean and Factory method
Feature | FactoryBean | Factory Method |
---|---|---|
Spring Integration | Implements FactoryBean | Regular method within the class @Configuration |
Bean instantiation | Spring calls getObject() on the FactoryBean | Spring calls the method directly |
Can it be a bean itself? | Yes, FactoryBean is registered as a bean | No, only the created object is registered as a bean |
Uses | Proxy objects, complex initialization, dynamic objects | Simple object creation, static factory methods |
Get the factory itself | Use &beanName to get the FactoryBean | No special call needed |
Supports singleton/prototype? | Yes, via isSingleton() method | Controlled via @Scope annotation |
When to Use? | If an object requires complex instantiation logic | If an object can be created with a simple factory method |
When should you use FactoryBean vs. factory method?
Use a FactoryBean
when:
- You need fine-grained control over bean instantiation (e.g. when creating dynamic proxies).
- The bean requires elaborate initialization and should be created lazily.
- The bean requires a runtime configuration before it is instantiated.
- You need a third-party object wrapper that does not integrate smoothly with Spring.
Use Factory Method when:
- The object can be created with a simple method call.
- The bean does not require Spring Lifecycle Control.
- You prefer a cleaner and simpler approach to instantiating objects.
Spring’s Built-in FactoryBeans
Spring provides several built-in FactoryBean
implementations to help developers create common objects more efficiently. These FactoryBean
classes abstract away the complex instantiation logic for commonly used objects, such as proxy objects, JDBC connections, JNDI lookups, and more.
In this section, we will explore some of the most commonly used FactoryBean
implementations in Spring.
Overview of the built-in FactoryBeans
Here are some of the major built-in FactoryBean
implementations in Spring:
FactoryBean Name | Purpose |
---|---|
ProxyFactoryBean | Creates dynamic proxy objects for AOP (Aspect-Oriented Programming) and method interception. |
TransactionProxyFactoryBean | Wraps a bean with a transactional proxy and thus enables declarative transaction management. |
JndiObjectFactoryBean | Searches and retrieves objects from a JNDI (Java Naming and Directory Interface) environment. |
LocalSessionFactoryBean | Configures and manages the SessionFactory of Hibernate. |
SqlSessionFactoryBean | Used in MyBatis to configure the SqlSessionFactory . |
ServiceLocatorFactoryBean | Creates service locator instances that are delegated to Spring-managed beans. |
BeanFactoryPostProcessor | Enables the customization of bean definitions before the beans are instantiated. |
ProxyFactoryBean | Creation of AOP proxies |
Spring’s ProxyFactoryBean
is one of the most commonly used implementations of the FactoryBean
. It is used to create dynamic proxy objects, which are essential for Aspect Oriented Programming (AOP), method security and transaction management.
Example: Creating a proxy for a service
<bean id="myService" class="com.example.MyService"/>
<bean id="proxyService" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="target" ref="myService"/>
<property name="interceptorNames">
<list>
<value>myMethodInterceptor</value>
</list>
</property>
</bean>
Here:
ProxyFactoryBean
creates a Proxy object forMyService
.- The proxy applies an interceptor (
myMethodInterceptor
) to dynamically change the method behavior.
When to use?
- When implementing AOP, logging or security logic.
- When creating transactional proxies.
TransactionProxyFactoryBean
– Activate transaction management
If you want to use transactions declaratively in Spring (without using annotations), TransactionProxyFactoryBean
will help you by creating transactional proxies.
Example: Transaction management with TransactionProxyFactoryBean
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory"/>
</bean>
<bean id="transactionProxy" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<property name="transactionManager" ref="transactionManager"/>
<property name="target" ref="myService"/>
<property name="transactionAttributes">
<props>
<prop key="save*">PROPAGATION_REQUIRED</prop>
<prop key="delete*">PROPAGATION_REQUIRED</prop>
</props>
</property>
</bean>
Here:
- A transactional proxy is created for
myService
, which ensures that the methodssave()
anddelete()
are executed within a transaction.
When to use?
- If you want to use transaction management declaratively.
- If you prefer an XML-based configuration over
@Transactional
annotation.
JndiObjectFactoryBean
– Access to JNDI resources
When integrated into Java EE applications, some resources (such as DataSource
, JMS ConnectionFactory
or EJBs
) are managed by an application server and accessed via JNDI (Java Naming and Directory Interface).
Instead of manually writing JNDI lookup code, you can use JndiObjectFactoryBean
.
Example: Looking up a DataSource via JNDI
<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="java:comp/env/jdbc/MyDataSource"/>
</bean>
Here:
- The
JndiObjectFactoryBean
retrieves theDataSource
object from JNDI and makes it available as a Spring bean.
When to use?
- If you are working in Java EE environments where the resources are managed by an application server.
- When you need to retrieve EJBs, JMS resources or DataSources dynamically.
LocalSessionFactoryBean
– Configure Hibernate
Spring’s LocalSessionFactoryBean
simplifies the setup of Hibernate’s SessionFactory
.
Example: Hibernate configuration
<bean id="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="packagesToScan" value="com.example.model"/>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
<prop key="hibernate.show_sql">true</prop>
</props>
</property>
</bean>
Here:
- The
LocalSessionFactoryBean
creates and configures a HibernateSessionFactory
. - It automatically applies Hibernate properties and scans entity classes.
When to use?
- When you set up Hibernate within a Spring application.
- When you want Spring to manage the Hibernate configuration dynamically.
SqlSessionFactoryBean
– Configure MyBatis
MyBatis, a popular ORM framework, uses SqlSessionFactoryBean
for session management.
Example: MyBatis configuration
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="mapperLocations" value="classpath:mappers/*.xml"/>
</bean>
Here:
SqlSessionFactoryBean
initializes MyBatis with a configured DataSource.- The mapper XML files are loaded automatically.
When to use?
- When working with the MyBatis ORM framework in a Spring application.
ServiceLocatorFactoryBean
– Creating service locators
the ServiceLocatorFactoryBean
helps to create service locator interfaces dynamically, reducing the need for manual lookup logic.
Example: Service Locator Interface
public interface PaymentServiceLocator {
PaymentService getPaymentService(String serviceType);
}
Example: Registering the ServiceLocatorFactoryBean
<bean id="paymentServiceLocator" class="org.springframework.beans.factory.config.ServiceLocatorFactoryBean">
<property name="serviceLocatorInterface" value="com.example.PaymentServiceLocator"/>
</bean>
Here:
- Spring automatically creates an implementation of
PaymentServiceLocator
which delegates calls to Spring-managed beans.
When to use?
- When implementing the Service Locator Pattern to dynamically manage multiple service implementations.
Configuring FactoryBeans in XML and Java Config
Now that we understand what FactoryBean
is and have learned about the built-in implementations, it’s time to see how to configure and use a FactoryBean
in Spring, both with XML-based configuration and Java-based configuration.
Spring allows you to define FactoryBeans in different ways, and the choice between XML and Java configuration depends on your project preferences and requirements.
XML-based configuration of FactoryBean
In the XML configuration we can define a FactoryBean
as a regular bean and retrieve the object it creates.
Example 1: Configuring a custom FactoryBean in XML
Let’s assume we have a CarFactoryBean
that produces Car
objects.
import org.springframework.beans.factory.FactoryBean;
public class CarFactoryBean implements FactoryBean {
private String model;
private String manufacturer;
public void setModel(String model) {
this.model = model;
}
public void setManufacturer(String manufacturer) {
this.manufacturer = manufacturer;
}
@Override
public Car getObject() {
return new Car(manufacturer, model);
}
@Override
public Class getObjectType() {
return Car.class;
}
@Override
public boolean isSingleton() {
return true;
}
}
XML configuration for FactoryBean
<bean id="carFactory" class="com.example.CarFactoryBean">
<property name="manufacturer" value="Tesla"/>
<property name="model" value="Model S"/>
</bean>
<bean id="car" factory-bean="carFactory" factory-method="getObject"/>
Here:
- autoFactory” is the
FactoryBean
itself. - auto” is the current car instance that was created using
carFactory.getObject()
.
Access to the FactoryBean itself in XML
By default, when we call getBean("carFactory")
, Spring returns the created Car
object, not the CarFactoryBean
.
However, if we need to retrieve the FactoryBean itself, we prefix the bean name with &
.
Example: Retrieving the FactoryBean instead of the produced object
CarFactoryBean factory = (CarFactoryBean) context.getBean("&carFactory");
The &carFactory
gets the actual FactoryBean
, not the Car
object that it creates.
Java-based configuration of the FactoryBean
For projects that use Java-based configuration (@Configuration + @Bean) instead of XML, we can define FactoryBean
instances with @Bean
methods.
Example 1: Defining a custom FactoryBean in the Java configuration
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration public class AppConfig {
@Bean
public CarFactoryBean carFactoryBean() {
CarFactoryBean factoryBean = new CarFactoryBean();
factoryBean.setManufacturer("Tesla");
factoryBean.setModel("Model X");
return factoryBean;
}
@Bean
public Car car(CarFactoryBean factoryBean) throws Exception {
return factoryBean.getObject(); // Get the current Car object
}
}
Here:
carFactoryBean()
registers theCarFactoryBean
.- auto()” calls “getObject()” to get the instance “Car”.
Example 2: Accessing FactoryBean in Java Config
CarFactoryBean factoryBean = (CarFactoryBean) context.getBean("&carFactoryBean");
The prefix & enables access to the FactoryBean
itself.
Use FactoryBean with @Autowired
If we need to inject a FactoryBean instead of the created object, we use @Autowired with @Qualifier("&beanName")
.
Example: Injecting a FactoryBean in Java Config
@Component public class FactoryBeanConsumer {
private final CarFactoryBean carFactoryBean;
@Autowired
public FactoryBeanConsumer(@Qualifier("&carFactoryBean") CarFactoryBean carFactoryBean) {
this.carFactoryBean = carFactoryBean;
}
public void printFactoryDetails() {
System.out.println("FactoryBean Class: " + carFactoryBean.getClass().getName());
}
}
This ensures that Spring injects the instance of the FactoryBean
and not the object that creates it.
FactoryBean in Spring Boot applications
In Spring Boot we usually prefer the Java-based configuration using @Bean
methods. However, FactoryBean
can still be used effectively.
Example: Using FactoryBean in a Spring Boot app
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration public class CarFactoryConfig {
@Bean
public CarFactoryBean carFactoryBean() {
return new CarFactoryBean();
}
@Bean
public Car car(CarFactoryBean factoryBean) throws Exception {
return factoryBean.getObject();
}
}
When a Spring Boot application is executed, this configuration ensures that Spring loads the Car object created by CarFactoryBean
.
FactoryBean vs. @Bean method – When should you use it?
Both the “FactoryBean” method and the “@Bean” method are used to define custom bean instantiation logic, but they serve different purposes.
Feature | FactoryBean | @Bean Method |
---|---|---|
Spring Integration | Implements FactoryBean | Regular method within the class @Configuration |
Bean instantiation | Spring calls getObject() | Spring calls the method directly |
Supports singleton/prototype? | Yes, via isSingleton() | Controlled via the annotation @Scope |
Used for? | Creating proxies, dynamic objects, complex initialization | Simple object instantiation |
Retrieve factory itself? | Use &beanName | Not applicable |
Use FactoryBean
if you instantiate objects dynamically, proxy objects, create expensive resources or integrate third-party libraries.
Use @Bean
when defining simple, directly instantiable beans.
Access to the FactoryBean itself
If a FactoryBean
is registered in the Spring container, the call to getBean("factoryBeanName")
by default returns the object created by the “FactoryBean” and not the “FactoryBean” instance itself.
In some cases, however, it may be necessary to access the actual instance of the FactoryBean
instead of the object created by it. Spring offers a special option for this with the prefix &
(ampersand).
Default behavior: Get the created object
Let’s assume we have a CarFactoryBean
that creates a Car
object.
import org.springframework.beans.factory.FactoryBean;
public class CarFactoryBean implements FactoryBean {
@Override
public Car getObject() {
return new Car("Tesla", "Model S");
}
@Override
public Class getObjectType() {
return Car.class;
}
@Override
public boolean isSingleton() {
return true;
}
}
Retrieve the produced bean (Car)
ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
Car car = context.getBean("carFactoryBean", Car.class);
System.out.println(car); // Output: Car{Manufacturer='Tesla', Model='Model S'}
Spring automatically calls getObject()
and returns the instance Car
.
Retrieve the FactoryBean instead of the created object
If we want to retrieve the **FactoryBean
itself, we use the prefix *&
(ampersand)* when calling getBean()
.
Example: Get the FactoryBean itself
CarFactoryBean factoryBean = (CarFactoryBean) context.getBean("&carFactoryBean");
System.out.println(factoryBean.getClass().getName());
// Output: com.example.CarFactoryBean
By adding “&”, we instruct Spring to return the “FactoryBean” instead of the created object
When should you access the FactoryBean?
Although in most cases we only need the created object, there are some scenarios where accessing the “FactoryBean” itself is useful:
debugging and inspection
If you want to check the internal state, configuration or properties of the factory, you may need access to the “FactoryBean”.
CarFactoryBean factoryBean = (CarFactoryBean) context.getBean("&carFactoryBean");
System.out.println("FactoryBean Class: " + factoryBean.getClass().getName());
Changing the configuration dynamically
If the FactoryBean
allows you to change its configuration, you can retrieve it and update its properties before calling getObject()
.
CarFactoryBean factoryBean = (CarFactoryBean) context.getBean("&carFactoryBean");
factoryBean.setManufacturer("BMW");
factoryBean.setModel("M5");
Car newCar = factoryBean.getObject();
System.out.println(newCar); // Output: Car{manufacturer='BMW', model='M5'}
This approach is useful if you are working with dynamic configurations.
Conditional bean creation
It may happen that you conditionally have to decide whether you want to call getObject()
or work with the FactoryBean
itself.
CarFactoryBean factoryBean = (CarFactoryBean) context.getBean("&carFactoryBean");
if (someCondition) {
Car car = factoryBean.getObject(); // Get the Car instance
} else {
System.out.println("Using factory settings only.");
}
Access to FactoryBean in XML configuration
If you are using an XML configuration, you can also retrieve the FactoryBean
with the prefix &
.
XML configuration for CarFactoryBean
<bean id="carFactoryBean" class="com.example.CarFactoryBean"/>
Retrieve CarFactoryBean in Java
CarFactoryBean factoryBean = (CarFactoryBean) context.getBean("&carFactoryBean");
The prefix “&” works in both XML and Java-based configurations
Access to FactoryBean in Java-based configuration (Spring Boot)
In Spring Boot, the process remains the same when using @Bean
configurations.
Java configuration for FactoryBean
@Configuration public class AppConfig {
@Bean
public CarFactoryBean carFactoryBean() {
return new CarFactoryBean();
}
}
Retrieving the FactoryBean in Spring Boot
ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
CarFactoryBean factoryBean = (CarFactoryBean) context.getBean("&carFactoryBean");
System.out.println("Retrieved FactoryBean: " + factoryBean.getClass().getName());
Works in the same way as in normal Spring applications.
Common pitfalls and best practices
Using FactoryBean
in Spring can be very powerful, but it also has potential pitfalls. Developers often encounter problems related to incorrect retrieval of beans, misconfiguration of singletons and prototypes, debugging difficulties and improper lifecycle management.
In this section, we look at common mistakes developers make when using FactoryBean
and the best practices to avoid them.
Common pitfalls with FactoryBean
Mistakenly retrieving the FactoryBean instead of the created object
One of the most common mistakes when using FactoryBean
is retrieving the FactoryBean
itself instead of the object it creates.
Incorrect usage: Retrieving the FactoryBean instead of the created object
CarFactoryBean factoryBean = (CarFactoryBean) context.getBean("carFactoryBean");
Car car= factoryBean.getObject(); // Throws ClassCastException
Why is this an error?
getBean("carFactoryBean")
returns the instanceCar
, notCarFactoryBean
.- Since
CarFactoryBean
implementsFactoryBean
, Spring automatically callsgetObject()
.
Correct usage
Car car = context.getBean("carFactoryBean", Car.class);
This correctly retrieves the Car object created by the factory.
Retrieving the FactoryBean itself
If you really need the FactoryBean
, use the prefix &
:
CarFactoryBean factoryBean = (CarFactoryBean) context.getBean("&carFactoryBean");
Configure singleton vs. prototype beans incorrectly
Spring’s FactoryBean
allows us to use the isSingleton()
method to control whether the created object should be a singleton or a prototype`.
Mistake: The method isSingleton()
was not overwritten correctly
@Override public boolean isSingleton() {
return false; // Always creates a new object (may be unintentional)
}
Why is this a mistake?
- If you don’t think about it carefully, you may unintentionally return a new instance every time a bean is requested, even if a singleton is expected.
Correct usage: Declare the correct singleton scope
@Override public boolean isSingleton() {
return true; // Ensures that a single instance is returned
}
Best Practice:
-Use true
for singleton beans (recommended for database connections, caches and expensive resources).
- Use
false
for prototype beans (if a new instance is needed for each request).
Use FactoryBean if it is not necessary
Not every bean needs a FactoryBean
. If an object can be created with a simple @Bean
method or a constructor injection, FactoryBean
is unnecessary.
Unnecessary use of FactoryBean
public class SimpleObjectFactoryBean implements FactoryBean {
@Override
public SimpleObject getObject() {
return new SimpleObject();
}
@Override
public Class getObjectType() {
return SimpleObject.class;
}
@Override
public boolean isSingleton() {
return true;
}
}
Why is this a mistake?
- The class simply calls
new SimpleObject()
insidegetObject()
, which can easily be done by a@Bean
method.
The right approach: Use @Bean instead
@Bean public SimpleObject simpleObject() {
return new SimpleObject();
}
Best Practice:
- Use
FactoryBean
only for complex objects that require additional configuration or cannot be instantiated directly.
Forgetting the correct implementation of getObjectType()
Spring refers to getObjectType()
to determine the type of the bean during autowiring and dependency injection.
Mistake: Return of null
in getObjectType()
@Override public Class getObjectType() {
return null; // Incorrect
}
Why is this a mistake?
- Spring is not able to determine the type of the bean, which leads to possible dependency injection errors.
Correct implementation
@Override public Class getObjectType() {
return SimpleObject.class; // Explicit specification of the type
}
Best Practice:
- Always return the correct class type in “getObjectType()” to improve compatibility with Spring.
Debugging problems with FactoryBean
Since FactoryBean
does not behave like a normal bean, debugging can be difficult.
Troubleshooting tips:
Check bean type in Spring context
System.out.println(context.getType("carFactoryBean"));
This outputs the type of the returned bean and helps to find out whether it is the FactoryBean
itself or the object created by it.
Check whether a bean is a FactoryBean
boolean isFactory = context.getBean("&carFactoryBean") instanceof FactoryBean;
System.out.println("Is FactoryBean: " + isFactory);
This allows you to determine whether a bean is actually a FactoryBean
.
Use of @Lazy
to delay the creation of the bean
If a FactoryBean
contains expensive initialization logic, mark it as @Lazy
to delay its creation.
@Bean
@Lazy public CarFactoryBean carFactoryBean() {
return new CarFactoryBean();
}
This ensures that Spring only creates the factory when needed.
Best practices for the use of FactoryBean
To avoid common pitfalls and ensure best practices when using FactoryBean
, follow these guidelines:
Use FactoryBean only when necessary
- Use
FactoryBean
only when an object requires complex instantiation logic. - Rather use
@Bean
for simple objects that can be created normally.
Retrieve the FactoryBean correctly
- Use
context.getBean("factoryBeanName")
to retrieve the produced object. - Use
context.getBean("&factoryBeanName")
to retrieve the FactoryBean itself.
Proper implementation of isSingleton()
- Returns
true
if the created bean should be a singleton. - Returns
false
if the created bean is to be a new instance each time.
Always define getObjectType()
- Helps Spring to determine autowiring compatibility.
- Avoids problems with dependency injection.
Use @Lazy
for expensive bean creation
- If object creation is resource intensive, mark the
FactoryBean
as@Lazy
to create it only when needed.
Use Spring Boot for simpler configurations
- If you are working in a Spring Boot project, you should prefer Java-based configuration (
@Bean
) over XML configuration to improve maintainability.
Conclusion
In this blog post, we explored Spring’s FactoryBean
, a powerful but often overlooked feature that provides fine-grained control over bean instantiation. We looked at the definition, use cases, implementation, configuration, built-in deployments, pitfalls and best practices.
Final thoughts
Spring’s FactoryBean
is a powerful feature that provides extended control over bean instantiation. While most applications do not need FactoryBean
in simple cases, it is essential for complex, dynamic or proxy-based object creation.
Key takeaways:
“factoryBean” enables dynamic and flexible bean creation.
It is used for AOP, ORM, third party integrations and expensive resource management.
Understanding when to use FactoryBean
vs @Bean
is crucial for better design.
Spring provides several built-in FactoryBean
implementations to simplify common tasks.
Avoid common pitfalls and follow best practices for effective use.
Now that you have a solid understanding of FactoryBean
, you can confidently use it in real Spring applications and optimize your bean management strategies!
