Understanding BeanFactory, ApplicationContext, and FactoryBean in Spring
This article explains the roles of BeanFactory and ApplicationContext in Spring, compares BeanFactory with FactoryBean, and provides detailed code examples showing how to configure and retrieve beans, including custom FactoryBean implementations and the use of '&' to access the FactoryBean itself.
BeanFactory is the original IoC container interface in Spring; implementations such as XmlBeanFactory provide basic bean creation but cannot support many Spring extensions like AOP or web features.
ApplicationContext extends BeanFactory, inheriting all its capabilities while adding message source support, resource loading, event propagation, and hierarchical context loading, and is generally recommended over BeanFactory.
Difference between BeanFactory and FactoryBean
BeanFactory is an interface that defines the core container contract, whereas FactoryBean is also an interface but represents a bean that itself acts as a factory, allowing custom creation logic similar to the Factory Method and Decorator patterns.
1. BeanFactory
BeanFactory is responsible for instantiating, locating, configuring application objects and managing their dependencies. It is an interface, not a concrete container; Spring provides several implementations such as DefaultListableBeanFactory , XmlBeanFactory , and ApplicationContext .
Typical XML configuration for an XmlBeanFactory loads bean definitions from a file:
Resource resource = new FileSystemResource("beans.xml");
BeanFactory factory = new XmlBeanFactory(resource);Another way uses classpath resources:
ClassPathResource resource = new ClassPathResource("beans.xml");
BeanFactory factory = new XmlBeanFactory(resource);Or using ApplicationContext for multiple configuration files:
ApplicationContext context = new ClassPathXmlApplicationContext(new String[]{"applicationContext.xml", "applicationContext-part2.xml"});
BeanFactory factory = (BeanFactory) context;BeanFactory exposes only six core methods, for example:
boolean containsBean(String beanName) – checks if a bean definition exists.
Object getBean(String name) – returns the bean instance, creating a singleton or a new instance as defined.
Object getBean(String name, Class requiredType) – returns the bean cast to the required type.
Class getType(String name) – returns the bean's class.
boolean isSingleton(String name) – indicates if the bean is a singleton.
String[] getAliases(String name) – returns all aliases for the bean.
2. FactoryBean
Spring provides the org.springframework.beans.factory.FactoryBean interface to let developers customize bean creation logic. Implementations can hide complex instantiation details and are widely used; Spring itself ships with dozens of FactoryBean implementations.
From Spring 3.0 onward, FactoryBean supports generics ( FactoryBean<T> ). When a bean definition specifies a class that implements FactoryBean , getBean("beanName") returns the object produced by FactoryBean#getObject() , not the FactoryBean instance itself. To obtain the FactoryBean itself, prefix the bean name with '&': getBean("&beanName") .
Example of a custom FactoryBean that creates a proxy and logs method calls:
/**
* MyFactoryBean – creates a proxy for a given interface and logs method invocation.
*/
public class MyFactoryBean implements FactoryBean
, InitializingBean, DisposableBean {
private static final Logger logger = LoggerFactory.getLogger(MyFactoryBean.class);
private String interfaceName;
private Object target;
private Object proxyObj;
@Override
public void destroy() throws Exception { logger.debug("destroy......"); }
@Override
public void afterPropertiesSet() throws Exception {
proxyObj = Proxy.newProxyInstance(this.getClass().getClassLoader(),
new Class[]{Class.forName(interfaceName)},
(proxy, method, args) -> {
logger.debug("invoke method......" + method.getName());
logger.debug("invoke method before......" + System.currentTimeMillis());
Object result = method.invoke(target, args);
logger.debug("invoke method after......" + System.currentTimeMillis());
return result;
});
logger.debug("afterPropertiesSet......");
}
@Override
public Object getObject() throws Exception { logger.debug("getObject......"); return proxyObj; }
@Override
public Class
getObjectType() { return proxyObj == null ? Object.class : proxyObj.getClass(); }
@Override
public boolean isSingleton() { return true; }
// getters and setters omitted for brevity
}Corresponding XML bean definition:
<bean id="fbHelloWorldService" class="com.ebao.xxx.MyFactoryBean">
<property name="interfaceName" value="com.ebao.xxx.HelloWorldService"/>
<property name="target" ref="helloWorldService"/>
</bean>JUnit test to verify the FactoryBean behavior:
@RunWith(JUnit4ClassRunner.class)
@ContextConfiguration(classes = { MyFactoryBeanConfig.class })
public class MyFactoryBeanTest {
@Autowired
private ApplicationContext context;
@Test
public void testFactoryBean() {
HelloWorldService helloWorldService = (HelloWorldService) context.getBean("fbHelloWorldService");
helloWorldService.getBeanName();
helloWorldService.sayHello();
}
}Another example shows a CarFactoryBean that parses a comma‑separated string to set all properties of a Car object:
public class CarFactoryBean implements FactoryBean<Car> {
private String carInfo; // e.g. "Ferrari,400,2000000"
@Override
public Car getObject() throws Exception {
Car car = new Car();
String[] infos = carInfo.split(",");
car.setBrand(infos[0]);
car.setMaxSpeed(Integer.valueOf(infos[1]));
car.setPrice(Double.valueOf(infos[2]));
return car;
}
@Override
public Class<Car> getObjectType() { return Car.class; }
@Override
public boolean isSingleton() { return false; }
public void setCarInfo(String carInfo) { this.carInfo = carInfo; }
}XML usage of the custom FactoryBean:
<bean id="car" class="com.baobaotao.factorybean.CarFactoryBean" p:carInfo="法拉利,400,2000000"/>When retrieving the bean with getBean("car") , Spring returns the Car instance produced by CarFactoryBean#getObject() . To obtain the FactoryBean itself, use getBean("&car") .
These examples demonstrate how BeanFactory, ApplicationContext, and FactoryBean work together in Spring to provide flexible, decoupled object creation and dependency injection.
Selected Java Interview Questions
A professional Java tech channel sharing common knowledge to help developers fill gaps. Follow us!
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.