Fading Coder

One Final Commit for the Last Sprint

Home > Tech > Content

Decoding Spring: Contrasting BeanFactory and FactoryBean Roles

Tech May 7 3

Two interfaces in the Spring ecosystem—BeanFactory and FactoryBean—often confuse developers because their names are visually similar. However, they serve fundamentally different purposes in the IoC container.

BeanFactory represents the IoC container itself, acting as a centralized registry that manages the complete lifecycle of beans. It reads bean definitions, instantiates objects, wires dependencies, and handles scopes. The core methods expose essential container capabilities:

public interface BeanFactory {
    String FACTORY_BEAN_PREFIX = "&";

    Object fetchBean(String name) throws BeansException;
    <T> T fetchBean(String name, Class<T> requiredType) throws BeansException;
    Object fetchBean(String name, Object... args) throws BeansException;
    <T> T fetchBean(Class<T> requiredType) throws BeansException;
    <T> T fetchBean(Class<T> requiredType, Object... args) throws BeansException;

    <T> ObjectProvider<T> resolveProvider(Class<T> requiredType);
    <T> ObjectProvider<T> resolveProvider(ResolvableType requiredType);

    boolean containsBeanDefinition(String name);
    boolean isSingletonScope(String name) throws NoSuchBeanDefinitionException;
    boolean isPrototypeScope(String name) throws NoSuchBeanDefinitionException;
    boolean matchesType(String name, ResolvableType typeToCheck) throws NoSuchBeanDefinitionException;
    boolean matchesType(String name, Class<?> typeToCheck) throws NoSuchBeanDefinitionException;

    @Nullable
    Class<?> resolveType(String name) throws NoSuchBeanDefinitionException;
    @Nullable
    Class<?> resolveType(String name, boolean allowFactoryBeanInit) throws NoSuchBeanDefinitionException;
    String[] getAliasNames(String name);
}

Key implementations of BeanFactory include ClassPathXmlApplicationContext (loading XML from classpath), FileSystemXmlApplicationContext (loading from absolute file paths), AnnotationConfigApplicationContext (driven by Java‑based configuration), and DefaultListableBeanFactory—a mature, feature‑rich container that merges ListableBeanFactory and BeanDefinitionRegistry.

In contrast, FactoryBean is a specialized bean that produces another bean with custom initialization logic. When a bean cannot be trivially instantiated via a constructor or setter injection—for example, when it requires complex builder patterns or external resource setup—FactoryBean encapsulates that complexity.

Consider three common configuration snippets:

<bean class="org.mybatis.spring.SqlSessionFactoryBean" id="sqlSessionFactoryBean">
    ...
</bean>

<bean class="org.apache.shiro.spring.web.ShiroFilterFactoryBean" id="shiroFilter">
    ...
</bean>

<bean class="org.springframework.format.support.FormattingConversionServiceFactoryBean" id="conversionService">
    ...
</bean>

Each class name ends with FactoryBean because the actual object registered in the container is not the factory bean itself, but the product it creates.

Take SqlSessionFactoryBean as an example. SqlSessionFactory is an interface; it cannot be generated with a simple new. Instead, it must be assembled through a SqlSessionFactoryBuilder that reads configuration files. The factory bean hides this procedure:

public class SqlSessionFactoryBean 
    implements FactoryBean<SqlSessionFactory>, InitializingBean, ApplicationListener<ApplicationEvent> {

    private SqlSessionFactory sessionFactory;

    @Override
    public SqlSessionFactory buildObject() throws Exception {
        if (this.sessionFactory == null) {
            afterPropertiesSet();
        }
        return this.sessionFactory;
    }

    @Override
    public Class<?> getProducedType() {
        return this.sessionFactory == null 
               ? SqlSessionFactory.class 
               : this.sessionFactory.getClass();
    }

    @Override
    public boolean producesSingleton() {
        return true;
    }
}

The FactoryBean contract requires three methods: buildObject() returns the actual bean to be registered; getProducedType() declares its runtime type; and producesSingleton() indicates singleton status. When the container ancounters a bean definition for SqlSessionFactoryBean, it internally calls buildObject() and registers the returned SqlSessionFactory, not the factory bean itself. To retrieve the raw factory bean instance, prefix the bean name with &.

Use FactoryBean whenever bean creation demands non‑trivial logic—such as proxy generation, resource loading, or conditional selection of implementation classes.

Tags: spring

Related Articles

Understanding Strong and Weak References in Java

Strong References Strong reference are the most prevalent type of object referencing in Java. When an object has a strong reference pointing to it, the garbage collector will not reclaim its memory. F...

Comprehensive Guide to SSTI Explained with Payload Bypass Techniques

Introduction Server-Side Template Injection (SSTI) is a vulnerability in web applications where user input is improper handled within the template engine and executed on the server. This exploit can r...

Implement Image Upload Functionality for Django Integrated TinyMCE Editor

Django’s Admin panel is highly user-friendly, and pairing it with TinyMCE, an effective rich text editor, simplifies content management significantly. Combining the two is particular useful for bloggi...

Leave a Comment

Anonymous

◎Feel free to join the discussion and share your thoughts.