Lazy Loading

Lazy-init means lazy loading of Bean. The default behavior of the ApplicationContext container is that all Singleton Beans are eagerly instantiated when the server starts.

Configuration Method

<!-- Default bean configuration -->
<bean id="wzkTestBean" class="wzk.WzkTestBean" lazy-init="false" />
  • false means immediate loading, instant initialization when Spring starts
  • true means lazy loading, initialization only on first call

If a bean1 set to immediate loading references a bean2 set to lazy loading, bean1 will be initialized when the container starts, and at this point, bean2 will also be instantiated.

You can also use the default-lazy-init attribute to control global lazy initialization:

<beans default-lazy-init="true">
    <!-- no beans will be eagerly pre-instantiated... -->
</beans>

When a bean’s scope is prototype, even if lazy-init=false is set, the container will not immediately initialize at startup. Instead, it will be instantiated only when the getBean method is called.

Application Scenarios

  • Enabling lazy loading can improve container startup performance and operation performance
  • For infrequently used Beans, instantiating only when occasionally needed saves resources

FactoryBean and BeanFactory

Basic Introduction

BeanFactory interface is the top-level interface of the container, defining the container’s basic behavior, responsible for producing and managing Bean factories. Its specific use is through sub-interface types such as ApplicationContext.

FactoryBean is a special type of Bean in Spring that can generate instances of a certain type. With its help, you can customize the Bean creation process. Spring has two types of Beans:

  • Regular Bean
  • Factory Bean (FactoryBean)

FactoryBean is similar to static factory methods and instance factory methods, but is more frequently used in the Spring framework and when integrating with third-party frameworks.

FactoryBean Interface Methods

public interface FactoryBean<T> {
    T getObject() throws Exception;          // Get instantiated object
    Class<?> getObjectType();                // Return object type
    boolean isSingleton();                   // Whether singleton
}

Code Example

WzkCompany Entity Class

@Data
@AllArgsConstructor
@NoArgsConstructor
public class WzkCompany {
    private String name;
    private String address;
    private String money;
}

WzkCompanyFactoryBean Implementation Class

public class WzkCompanyFactoryBean implements FactoryBean<WzkCompany> {
    private String wzkCompanyInfo;

    public void setWzkCompanyInfo(String wzkCompanyInfo) {
        this.wzkCompanyInfo = wzkCompanyInfo;
    }

    @Override
    public WzkCompany getObject() throws Exception {
        WzkCompany wzkCompany = new WzkCompany();
        String[] strs = wzkCompanyInfo.split(",");
        wzkCompany.setName(strs[0]);
        wzkCompany.setAddress(strs[1]);
        wzkCompany.setMoney(strs[2]);
        return wzkCompany;
    }

    @Override
    public Class<?> getObjectType() {
        return WzkCompany.class;
    }

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

XML Configuration

<bean id="wzkCompanyBean" class="wzk.factory.WzkCompanyFactoryBean">
    <property name="companyInfo" value="Company Name,Company Address,1000"></property>
</bean>

Test Run

// Get the object created by FactoryBean
Object wzkCompany = applicationContext.getBean("wzkCompanyBean");
// Output: WzkCompany(name=Company Name, address=Company Address, money=1000)

// Get the FactoryBean itself, need to add & prefix
Object factoryBean = applicationContext.getBean("&wzkCompanyBean");
// Output: wzk.factory.WzkCompanyFactoryBean@xxxx

Post-Processors

Spring provides two extension interfaces for post-processing Beans:

  • BeanPostProcessor
  • BeanFactoryPostProcessor

Execution order: Factory initializes BeanFactory → Bean objects → After BeanFactory initialization, use BeanFactoryPostProcessor → After Bean instantiation, use BeanPostProcessor

Note: An object is not necessarily a SpringBean, but a SpringBean is always an object.

BeanPostProcessor

BeanPostProcessor is bean-level processing, which can handle specific Beans.

public interface BeanPostProcessor {
    // Executed before initialization method
    Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;
    // Executed after initialization method
    Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;
}

Explanation:

  • The initialization method refers to the method specified by init-method
  • By default, it processes all Beans in the entire Spring container
  • You can use the beanName parameter to determine which specific Bean to process
  • Processing occurs after Spring container instantiation and dependency injection

BeanFactoryPostProcessor

BeanFactoryPostProcessor is BeanFactory-level processing, which handles the entire Bean factory. A typical application is PropertyPlaceholderConfigurer.

public interface BeanFactoryPostProcessor {
    void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;
}

You can use the getBeanDefinition method to get the BeanDefinition object and modify the property values defined in the Bean tag.

Note: When the BeanFactoryPostProcessor method is called, the Bean has not yet been instantiated. At this point, the Bean has just been parsed as a BeanDefinition object.


Summary

ConceptDescription
BeanFactoryTop-level IoC container interface, responsible for producing and managing Beans
FactoryBeanSpecial Bean for customizing Bean creation process
BeanPostProcessorBean-level post-processing, executes before and after initialization
BeanFactoryPostProcessorFactory-level post-processing, executes before Bean instantiation