1. 程式人生 > >Spring原始碼解析—第四篇IOC之BeanPostProcessor

Spring原始碼解析—第四篇IOC之BeanPostProcessor

1、BeanPostProcessor簡介

BeanPostProcessor是Spring IOC容器給我們提供的一個擴充套件介面。介面宣告如下:

public interface BeanPostProcessor {
    //bean初始化方法呼叫前被呼叫
    Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;
    //bean初始化方法呼叫後被呼叫
    Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;

}

BeanPostProcessor介面有兩個回撥方法。當一個BeanPostProcessor的實現類註冊到Spring IOC容器後,對於該Spring IOC容器所建立的每個bean例項在初始化方法呼叫前,將會呼叫BeanPostProcessor中的postProcessBeforeInitialization方法,而在bean例項初始化方法呼叫完成後,則會呼叫BeanPostProcessor中的postProcessAfterInitialization方法。

2、例項

修改上面的例項,增加ChangeUserBeanPostProcessor

2.1、ChangeUserBeanPostProcessor類

package com.vesus.spring.processor;

import com.vesus.spring.model.User;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;

/**
 * @Description:
 * @Author: vesus
 * @CreateDate: 2018/6/3 下午3:51
 * @Version: 1.0
 */
public class ChangeUserBeanPostProcessor implements BeanPostProcessor {
    //初始化之前處理
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {

        if (bean instanceof User){
            User user = (User) bean;
            user.setName("我是小明!");
        }

        return bean;
    }

    //初始化之後處理
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        return bean;
    }
}

2.2、配置檔案增加

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="user" class="com.vesus.spring.model.User" />
    <bean id="changeUser" class="com.vesus.spring.processor.ChangeUserBeanPostProcessor"/>
</beans>

2.3、測試類

public class Test {
    public static void main(String[] args) {
        BeanFactory beanFactory = new ClassPathXmlApplicationContext("applicationContext.xml");
        User user = (User) beanFactory.getBean("user") ;
        System.err.println(user.getName()+":"+user.getDesc());
    }
}

2.4、測試結果

我是小明!:使用者類

3、原始碼分析

3.1、入口方法refresh()

public void refresh() throws BeansException, IllegalStateException {
        synchronized (this.startupShutdownMonitor) {
            .....
            try {
                ......
                //開始註冊BeanPostProcessor來攔截其他的bean的初始化過程
                registerBeanPostProcessors(beanFactory);
                .....
                //初始化單例
                finishBeanFactoryInitialization(beanFactory);
                .....
            }

            catch (BeansException ex) {
                if (logger.isWarnEnabled()) {
                    logger.warn("Exception encountered during context initialization - " +
                            "cancelling refresh attempt: " + ex);
                }

                // Destroy already created singletons to avoid dangling resources.
                destroyBeans();

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

                // Propagate exception to caller.
                throw ex;
            }

            finally {
                // Reset common introspection caches in Spring's core, since we
                // might not ever need metadata for singleton beans anymore...
                resetCommonCaches();
            }
        }
    }

從入口方法中可以看到,BeanPostProcessor 的註冊方法registerBeanPostProcessors,下面分析registerBeanPostProcessors 的註冊過程

3.2、registerBeanPostProcessors註冊方法解析

public static void registerBeanPostProcessors(
            ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {
        // 獲取所有BeanPostProcessor型別的bean名稱
        String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);

        // 註冊BeanPostProcessorChecker,它可以列印BeanPostProcessor例項化過程中建立bean的日誌資訊
        // 計算已註冊的bean + 1 +上面獲取到的bean的數量,1是即將建立的BeanPostProcessorChecker
        int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
        beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));

        // 按照優先的、內部的、排序的、無排序的進行分組排序,
        // 其中優先bean多了MergedBeanDefinitionPostProcessor型別(merged bean definition)
        List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
        List<BeanPostProcessor> internalPostProcessors = new ArrayList<>();
        List<String> orderedPostProcessorNames = new ArrayList<>();
        List<String> nonOrderedPostProcessorNames = new ArrayList<>();
        for (String ppName : postProcessorNames) {
            if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
                BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
                priorityOrderedPostProcessors.add(pp);
                if (pp instanceof MergedBeanDefinitionPostProcessor) {
                    internalPostProcessors.add(pp);
                }
            }
            else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
                orderedPostProcessorNames.add(ppName);
            }
            else {
                nonOrderedPostProcessorNames.add(ppName);
            }
        }

        //註冊優先Order的後處理器
        sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
        registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);

        //註冊實現Ordered的後處理器
        List<BeanPostProcessor> orderedPostProcessors = new ArrayList<>();
        for (String ppName : orderedPostProcessorNames) {
            BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
            orderedPostProcessors.add(pp);
            if (pp instanceof MergedBeanDefinitionPostProcessor) {
                internalPostProcessors.add(pp);
            }
        }
        sortPostProcessors(orderedPostProcessors, beanFactory);
        registerBeanPostProcessors(beanFactory, orderedPostProcessors);

        // 註冊未排序的處理器
        List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<>();
        for (String ppName : nonOrderedPostProcessorNames) {
            BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
            nonOrderedPostProcessors.add(pp);
            if (pp instanceof MergedBeanDefinitionPostProcessor) {
                internalPostProcessors.add(pp);
            }
        }
        registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);

        // 註冊內部的處理器
        sortPostProcessors(internalPostProcessors, beanFactory);
        registerBeanPostProcessors(beanFactory, internalPostProcessors);

        // 註冊BeanPostProcessor:ApplicationListenerDetector,這個是AbstractApplicationContext的內部類
        beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
    }

3.3、呼叫方法finishBeanFactoryInitialization解析

Bean 的例項化程式碼,是從 finishBeanFactoryInitialization 方法開始的

protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
        if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&
                beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
            beanFactory.setConversionService(
                    beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
        }

        if (!beanFactory.hasEmbeddedValueResolver()) {
            beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));
        }

        String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
        for (String weaverAwareName : weaverAwareNames) {
            getBean(weaverAwareName);
        }

        beanFactory.setTempClassLoader(null);
        beanFactory.freezeConfiguration();

        //進行類的初始化
        beanFactory.preInstantiateSingletons();
    }

從上面程式碼中可以發現 Bean 的例項化是呼叫的是preInstantiateSingletons方法,接續往下找我們會找到AbstractAutowireCapableBeanFactory的doCreateBean方法。

3.4、doCreateBean方法解析

protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
            throws BeanCreationException {

        //初始化一個BeanWrapper
        BeanWrapper instanceWrapper = null;
        if (mbd.isSingleton()) {
            instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
        }
        if (instanceWrapper == null) {
            //建立bean例項
            instanceWrapper = createBeanInstance(beanName, mbd, args);
        }
        .....
        //初始化bean例項
        Object exposedObject = bean;
        try {
            populateBean(beanName, mbd, instanceWrapper);
            exposedObject = initializeBean(beanName, exposedObject, mbd);
        }
    }

在該方法中,呼叫createBeanInstance方法,建立bean例項物件,之後再呼叫方法initializeBean,進行相關初始化工作。

3.5、initializeBean方法解析

protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
        if (System.getSecurityManager() != null) {
            AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
                invokeAwareMethods(beanName, bean);
                return null;
            }, getAccessControlContext());
        }
        else {

            invokeAwareMethods(beanName, bean);
        }
        Object wrappedBean = bean;
        if (mbd == null || !mbd.isSynthetic()) {
            //在初始化之前處理執行處理器
            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()) {
            //在初始化之後處理執行處理器
            wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
        }

        return wrappedBean;
    }

至此,BeanPostProcessor的原始碼分析完成。