Spring Q & a series 1 -- differences between beanfactorypostprocessor and BeanPostProcessor

Posted by jvrothjr on Mon, 25 Nov 2019 21:52:04 +0100

It seems that BeanFactoryProcessor and BeanPostProcessor can control the instantiation process of Bean. This article will explain the concepts and differences between them.

What is BeanFactoryPostProcessor

The source code of BeanFactoryPostProcessor is as follows:

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

BeanFactoryPostProcessor is the processing of BeanFactory level, which is for the whole Bean factory. If you use a custom BeanFactoryProcessor, the execution path is as follows:

org.springframework.context.support.AbstractApplicationContext#refresh
    org.springframework.context.support.AbstractApplicationContext#invokeBeanFactoryPostProcessors
        org.springframework.context.support.PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors(org.springframework.beans.factory.config.ConfigurableListableBeanFactory, java.util.List<org.springframework.beans.factory.config.BeanFactoryPostProcessor>)
            org.springframework.context.support.PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors(java.util.Collection<? extends org.springframework.beans.factory.config.BeanFactoryPostProcessor>, org.springframework.beans.factory.config.ConfigurableListableBeanFactory)
                org.springframework.beans.factory.config.BeanFactoryPostProcessor#postProcessBeanFactory
                    com.jackwu.spring.config.customBeanFactoryPostProcessor#postProcessBeanFactory

What is bean processor

The source code of BeanPostProcessor is as follows:

public interface BeanPostProcessor {
	Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;
	Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;
}

The postProcessBeforeInitialization method works before bean initialization, and the postProcessBeforeInitialization method works after bean initialization.

The execution process of postProcessBeforeInitialization is as follows:

org.springframework.context.support.AbstractApplicationContext#refresh
    org.springframework.context.support.AbstractApplicationContext#finishBeanFactoryInitialization
        org.springframework.beans.factory.config.ConfigurableListableBeanFactory#preInstantiateSingletons
            org.springframework.beans.factory.support.AbstractBeanFactory#getBean(java.lang.String)
                org.springframework.beans.factory.support.AbstractBeanFactory#doGetBean
                    org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#getSingleton(java.lang.String, org.springframework.beans.factory.ObjectFactory<?>)
                        org.springframework.beans.factory.ObjectFactory#getObject
                            org.springframework.beans.factory.support.AbstractBeanFactory#createBean
                                org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean
                                    org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#initializeBean(java.lang.String, java.lang.Object, org.springframework.beans.factory.support.RootBeanDefinition)
                                        org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsBeforeInitialization
                                          org.springframework.beans.factory.config.BeanPostProcessor#postProcessBeforeInitialization

The key code of AbstractAutowireCapableBeanFactory.java is as follows:

Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
    // Execute postProcessBeforeInitialization
	wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}

try {
	invokeInitMethods(beanName, wrappedBean, mbd);
} catch (Throwable ex) {
	throw new BeanCreationException(
	(mbd != null ? mbd.getResourceDescription() : null),
		beanName, "Invocation of init method failed", ex);
}
if (mbd == null || !mbd.isSynthetic()) {
    // Execute postProcessAfterInitialization
    wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}

Difference between them

Both of the above provide Spring with an interface for postprocessing beans, but the timing of their execution is different. The former is after instantiation and the latter is before instantiation. In terms of function, the latter is more powerful in bean processing.

Topics: Java Spring