BeanPostProcessor和BeanFactoryProcessor淺析

1、簡(jiǎn)介

BeanPostProcessor和BeanFactoryProcessor是Spring中很重要的了兩個(gè)接口。我們先來(lái)看看Spring的文檔中對(duì)BeanPostProcessor的定義:

The BeanPostProcessor interface defines callback methods that you can 
implement to provide your own (or override the container’s default) 
instantiation logic, dependency-resolution logic, and so forth. If you want 
to implement some custom logic after the Spring container finishes 
instantiating, configuring,and initializing a bean, you can plug in one or 
more BeanPostProcessor implementations.

BeanPostProcessor 接口定義了一個(gè)你可以自己實(shí)現(xiàn)的回調(diào)方法,來(lái)實(shí)現(xiàn)你自己的實(shí)例化邏輯、依賴(lài)解決邏輯等,如果你想要在Spring完成對(duì)象實(shí)例化、配置、初始化之后實(shí)現(xiàn)自己的業(yè)務(wù)邏輯,你可以補(bǔ)充實(shí)現(xiàn)一個(gè)或多個(gè)BeanPostProcessor的實(shí)現(xiàn)。

我們?cè)賮?lái)看一下文檔那個(gè)中對(duì)BeanFactoryPostProcessor的描述:

The semantics of this interface are similar to those of the 
BeanPostProcessor, with one major difference:BeanFactoryPostProcessor 
operates on the bean configuration metadata; that is, the Spring IoC 
container allows a BeanFactoryPostProcessor to read the configuration 
metadata and potentially change it before the container instantiates any 
beans other than BeanFactoryPostProcessors.

BeanFactoryPostProcessor的定義和BeanPostProcessor相似,有一個(gè)最主要的不同是:BeanFactoryPostProcessor可以對(duì)bean的配置信息進(jìn)行操作;更確切的說(shuō)Spring IOC容器允許BeanFactoryPostProcessor讀取配置信息并且能夠在容器實(shí)例化任何其他bean(所有的實(shí)現(xiàn)了BeanFactoryPostProcessor接口的類(lèi))之前改變配置信息

2、BeanPostProcessor和BeanFactoryProcessor的定義

BeanPostProcessor有兩個(gè)方法:

public interface BeanPostProcessor {

    /**
     * Apply this BeanPostProcessor to the given new bean instance <i>before</i> any bean
     * initialization callbacks (like InitializingBean's {@code afterPropertiesSet}
     * or a custom init-method). The bean will already be populated with property values.
     * The returned bean instance may be a wrapper around the original.
     * @param bean bean的實(shí)例
     * @param beanName bean的name
     * @return 返回處理過(guò)后的bean,可以是最初的Bean或者是包裝后的Bean;
     * 如果返回null,后續(xù)的BeanPostProcessor不會(huì)被執(zhí)行
     * @throws org.springframework.beans.BeansException in case of errors
     * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet
     */
    Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;

    /**
     * Apply this BeanPostProcessor to the given new bean instance <i>after</i> any bean
     * initialization callbacks (like InitializingBean's {@code afterPropertiesSet}
     * or a custom init-method). The bean will already be populated with property values.
     * The returned bean instance may be a wrapper around the original.
     * <p>In case of a FactoryBean, this callback will be invoked for both the FactoryBean
     * instance and the objects created by the FactoryBean (as of Spring 2.0). The
     * post-processor can decide whether to apply to either the FactoryBean or created
     * objects or both through corresponding {@code bean instanceof FactoryBean} checks.
     * <p>This callback will also be invoked after a short-circuiting triggered by a
     * {@link InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation} method,
     * in contrast to all other BeanPostProcessor callbacks.
     * @param bean bean的實(shí)例
     * @param beanName bean的name
     * @return 返回處理過(guò)后的bean,可以是最初的Bean或者是包裝后的Bean;
     * 如果返回null,后續(xù)的BeanPostProcessor不會(huì)被執(zhí)行
     * {@code null}, no subsequent BeanPostProcessors will be invoked
     * @throws org.springframework.beans.BeansException in case of errors
     * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet
     * @see org.springframework.beans.factory.FactoryBean
     */
    Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;

}

我們可以看到注釋postProcessBeforeInitialization方法是在所有的bean的InitializingBean的afterPropertiesSet方法之前執(zhí)行而postProcessAfterInitialization方法則是在所有的bean的InitializingBean的afterPropertiesSet方法之后執(zhí)行的。

而B(niǎo)eanFactoryPOSTProcessor只有一個(gè)方法:

 */
public interface BeanFactoryPostProcessor {

    /**
     * Modify the application context's internal bean factory after its standard
     * initialization. All bean definitions will have been loaded, but no beans
     * will have been instantiated yet. This allows for overriding or adding
     * properties even to eager-initializing beans.
     * @param beanFactory the bean factory used by the application context
     * @throws org.springframework.beans.BeansException in case of errors
     */
    void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;

}

我們可以看到注釋中寫(xiě)到的:postProcessBeanFactory可以在BeanFactory完成實(shí)例化后修改容器內(nèi)部的BeanFactory。這時(shí)候所有的bean都被加載,但是沒(méi)有bean被初始化。這就允許BeanFactoryPOSTProcessor重寫(xiě)或者添加配置,甚至可以提前初始化bean。
好了,說(shuō)了這么多,也許大家對(duì)BeanPostProcessor和BeanFactoryProcessor還是有些迷惑,我們來(lái)看一個(gè)例子就能明白了:

3、示例

我們先創(chuàng)建一個(gè)類(lèi)實(shí)現(xiàn)BeanPostProcessor:

public class TestBeanPostProcessor implements BeanPostProcessor {
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println(beanName + "-->" + "TestBeanPostProcessor->postProcessBeforeInitialization");
        return bean;
    }

    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println(beanName + "-->" + "TestBeanPostProcessor->postProcessAfterInitialization");
        return bean;
    }
}

在創(chuàng)建一個(gè)類(lèi)實(shí)現(xiàn)BeanFactoryPostProcessor:

public class TestBeanFactoryPostPorcessor implements BeanFactoryPostProcessor {
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        System.out.println("TestBeanFactoryPostPorcessor->postProcessBeanFactory");
    }
}

然后創(chuàng)建一個(gè)普通的bean,實(shí)現(xiàn)了InitializingBean和DisposableBean接口:

public class TestBean implements InitializingBean, DisposableBean{
    private String name;
    private int age;

    public TestBean() {
        System.out.println("TestBean->constrcutor");
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        System.out.println("TestBean->setter");
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        System.out.println("TestBean->setter");
        this.age = age;
    }

    public void destroy() throws Exception {
        System.out.println("TestBean->destroy");
    }

    public void afterPropertiesSet() throws Exception {
        System.out.println("TestBean->afterPropertiesSet");
    }
}

然后在xml文件中注冊(cè)這三個(gè)bean:

    <bean id="testBeanPostProcessor" class="wbx.test_spring_noweb.beans.TestBeanPostProcessor"></bean>
    <bean id="testBeanFactoryPostProcessor" class="wbx.test_spring_noweb.beans.TestBeanFactoryPostPorcessor"></bean>
    <bean id="testBean" class="wbx.test_spring_noweb.beans.TestBean">
        <property name="name" value="丑星星"></property>
        <property name="age" value="18"></property>
    </bean>

最后寫(xiě)測(cè)試類(lèi)運(yùn)行:

public class Test {
    public static void main(String[] args) {
        FileSystemXmlApplicationContext context = new FileSystemXmlApplicationContext("classpath:wbx/test_spring_noweb/beans.xml");
        TestBean testBean = (TestBean)context.getBean("testBean");
        context.destroy();

    }
}

我們可以看到控制臺(tái)的運(yùn)行結(jié)果,這里截圖一部分:

測(cè)試運(yùn)行結(jié)果

我們可以看到Bean的生命周期:
1、解析xml文件,解析出BeanDefinition
2、Spring容器創(chuàng)建BeanFactoryPostProcessor實(shí)例
3、調(diào)用BeanFactoryPostProcessor的postProcessBeanFactory方法
4、Spring容器創(chuàng)建BeanPostProcessor實(shí)例
5、在需要?jiǎng)?chuàng)建其他Bean實(shí)例的時(shí)候創(chuàng)建其他Bean
6、調(diào)用Bean的構(gòu)造方法
7、調(diào)用Bean的setter方法為Bean屬性賦值
8、調(diào)用BeanPostProcessor的postProcessBeforeInitialization方法
9、調(diào)用InitializingBean的afterPropertiesSet方法
10、調(diào)用BeanPostProcessor的postProcessAfterInitialization方法
11、容器銷(xiāo)毀的時(shí)候調(diào)用DisposableBean的destroy方法

4、BeanPostProcessor在Spring內(nèi)部的使用舉例

我們都知道,當(dāng)一個(gè)Bean實(shí)現(xiàn)了OoXxAware接口后,Spring就會(huì)自動(dòng)將OoXx對(duì)象注入,例如:一個(gè)Bean實(shí)現(xiàn)了ApplicationContextAware接口,Spring會(huì)嘗試將ApplicationContext對(duì)象注入到這個(gè)Bean中,這是怎么實(shí)現(xiàn)的呢?
當(dāng)Spring容器初始化時(shí),會(huì)先解析Bean的定義,將定義解析成BeanDefinition對(duì)象,并且由BeanDefinitionHolder包裝一層,注冊(cè)到BeanFactory中。我們可以看一下容器刷新的方法(AbstractApplicationContext類(lèi)中的):

public void refresh() throws BeansException, IllegalStateException {
        synchronized (this.startupShutdownMonitor) {
            // Prepare this context for refreshing.
            prepareRefresh();

            // Tell the subclass to refresh the internal bean factory.
            ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

            // Prepare the bean factory for use in this context.
            prepareBeanFactory(beanFactory);

            try {
                // Allows post-processing of the bean factory in context subclasses.
                postProcessBeanFactory(beanFactory);

                // Invoke factory processors registered as beans in the context.
                invokeBeanFactoryPostProcessors(beanFactory);

                // Register bean processors that intercept bean creation.
                registerBeanPostProcessors(beanFactory);

                // Initialize message source for this context.
                initMessageSource();

                // Initialize event multicaster for this context.
                initApplicationEventMulticaster();

                // Initialize other special beans in specific context subclasses.
                onRefresh();

                // Check for listener beans and register them.
                registerListeners();

                // Instantiate all remaining (non-lazy-init) singletons.
                finishBeanFactoryInitialization(beanFactory);

                // Last step: publish corresponding event.
                finishRefresh();
            }

            catch (BeansException ex) {
                // Destroy already created singletons to avoid dangling resources.
                destroyBeans();

                // Reset 'active' flag.
                cancelRefresh(ex);

                // Propagate exception to caller.
                throw ex;
            }
        }
    }

解析Bean在ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();中完成。有興趣的同學(xué)可以自己看一下。然后調(diào)用postProcessBeanFactory(beanFactory);方法,我們看一下這個(gè)方法:

    protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
        // Tell the internal bean factory to use the context's class loader etc.
        beanFactory.setBeanClassLoader(getClassLoader());
        beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver());
        beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));

        // Configure the bean factory with context callbacks.
        beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
        beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
        beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
        beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
        beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
        beanFactory.ignoreDependencyInterface(EnvironmentAware.class);

        // BeanFactory interface not registered as resolvable type in a plain factory.
        // MessageSource registered (and found for autowiring) as a bean.
        beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
        beanFactory.registerResolvableDependency(ResourceLoader.class, this);
        beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
        beanFactory.registerResolvableDependency(ApplicationContext.class, this);

        // Detect a LoadTimeWeaver and prepare for weaving, if found.
        if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
            beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
            // Set a temporary ClassLoader for type matching.
            beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
        }

        // Register default environment beans.
        if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
            beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
        }
        if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
            beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
        }
        if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
            beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
        }
    }

這個(gè)方法其實(shí)就是為BeanFactory初始化一些屬性的值。
我們可以看到有一個(gè)行代碼:beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
ApplicationContextAwareProcessor實(shí)現(xiàn)了BeanPostProcessor接口。這行代碼將ApplicationContextAwareProcessor注冊(cè)到beanFactory的BeanPostProcessor集合中。我們?cè)賮?lái)看一下ApplicationContextAwareProcessor的部分代碼:

@Override
    public Object postProcessBeforeInitialization(final Object bean, String beanName) throws BeansException {
        AccessControlContext acc = null;

        if (System.getSecurityManager() != null &&
                (bean instanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware ||
                        bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware ||
                        bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware)) {
            acc = this.applicationContext.getBeanFactory().getAccessControlContext();
        }

        if (acc != null) {
            AccessController.doPrivileged(new PrivilegedAction<Object>() {
                @Override
                public Object run() {
                    invokeAwareInterfaces(bean);
                    return null;
                }
            }, acc);
        }
        else {
            invokeAwareInterfaces(bean);
        }

        return bean;
    }

    private void invokeAwareInterfaces(Object bean) {
        if (bean instanceof Aware) {
            if (bean instanceof EnvironmentAware) {
                ((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment());
            }
            if (bean instanceof EmbeddedValueResolverAware) {
                ((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(
                        new EmbeddedValueResolver(this.applicationContext.getBeanFactory()));
            }
            if (bean instanceof ResourceLoaderAware) {
                ((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext);
            }
            if (bean instanceof ApplicationEventPublisherAware) {
                ((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(this.applicationContext);
            }
            if (bean instanceof MessageSourceAware) {
                ((MessageSourceAware) bean).setMessageSource(this.applicationContext);
            }
            if (bean instanceof ApplicationContextAware) {
                ((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);
            }
        }
    }

ApplicationContextAwareProcessor會(huì)先判斷bean是否實(shí)現(xiàn)了Aware接口,如果是,再根據(jù)Aware的類(lèi)型來(lái)調(diào)用相應(yīng)的定義的接口來(lái)給Bean注入相應(yīng)的資源。

5、總結(jié)

BeanPostProcessor和BeanFactoryProcessor的區(qū)別是重點(diǎn),也是面試的時(shí)候經(jīng)??嫉摹8匾氖且粋€(gè)Ben的生命周期,希望大家可以重點(diǎn)看一下第三部分的示例,好好理解Bean的生命周期!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容