Spring源码学习系列(四)之PostProcessor扩展点

上次文章粗略写完了如何从beanFactory.getBean(beanName)中获取一个完整的bean,以及其中bean的创建以及初始化等。在bean的创建以及BeanFactory的初始化前后会发现有不少扩展点,即xxxPostProcessor,是Spring提供的扩展模式。

那么这篇就来探讨一下Spring的后置处理器以及核心的refresh()容器加载过程。

1、惯例,从最简单的xxxxApplicationContext加载配置bean开始

        //使用Configuration加载的话可直接使用AnnotationConfigApplicationContext进行加载
        ClassPathXmlApplicationContext act = new ClassPathXmlApplicationContext("beans.xml");

    public ClassPathXmlApplicationContext(
            String[] configLocations, boolean refresh, @Nullable ApplicationContext parent)
            throws BeansException {
        super(parent);
        setConfigLocations(configLocations);
        if (refresh) {
            refresh();
        }
    }

1.1、进入构造方法,发现主要有两个方法:

  • setConfigLocations(String...configLocations) : 解析配置文件的位置,可设置多个参数
  • refresh() : 容器刷新方法,给IOC容器添加组件和初始化 单实例bean,后置处理机制,ApplicationEvent机制 等核心功能

1.2、下面主要记录一下refresh()方法的主要过程,没有删除原来的英文注释。有理解错误请看英文作者注释

    //相当于AbstractBeanFactory.loadBeanDefinition的增强版
    @Override
    public void refresh() throws BeansException, IllegalStateException {
        synchronized (this.startupShutdownMonitor) {
            //刷新前的预准备工作,初始化了Environment,对系统属性和环境变量等属性进行提前检测,还有ApplicationEvents相关
            prepareRefresh();

            // Tell the subclass to refresh the internal bean factory.
            //刷新父容器(BeanFactory)并返回
            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.
                // 在BeanFactory初始化之后执行,在子类中可执行自定义增强
                postProcessBeanFactory(beanFactory);

                // Invoke factory processors registered as beans in the context.
                //注册所有的BeanFactoryPostProcessor
                invokeBeanFactoryPostProcessors(beanFactory);

                // Register bean processors that intercept bean creation.
                //注册所有的BeanPostProcessor拦截bean的创建
                registerBeanPostProcessors(beanFactory);

                // Initialize message source for this context.
                //初始化MessageSource
                initMessageSource();

                // Initialize event multicaster for this context.
                //初始化容器上下文时间派发器
                initApplicationEventMulticaster();

                // Initialize other special beans in specific context subclasses.
                //在子容器中初始化特殊的bean
                onRefresh();

                // Check for listener beans and register them.
                //注册事件监听,并使用ApplicationEventMulticaster发送事件
                registerListeners();

                // Instantiate all remaining (non-lazy-init) singletons.
                //初始化所有的单实例bean
                finishBeanFactoryInitialization(beanFactory);

                // Last step: publish corresponding event.
                //完成刷新操作,发出完成的监听事件
                finishRefresh();
            }

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

                //抛出异常则销毁所有的bean,并退出容器刷新过程
                // 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();
            }
        }
    }

如图,过程相当复杂和繁琐。我们拆分成小步骤逐个击破

  • 容器刷新预准备工作
        // 初始化PropertySource
        initPropertySources();

        // Validate that all properties marked as required are resolvable:
        // see ConfigurablePropertyResolver#setRequiredProperties
        //校验PropertySource
        getEnvironment().validateRequiredProperties();

有两个重要的操作:

  • 可以子类中重写并扩展初始化 : initPropertySource()
  • 检测属性是否正确的 : validateRequiredProperties()

下面简单模拟扩展操作,重写了ClassPathXmlApplicationContext中的inintProperty()

//自定义ApplicationContext,扩展initPropertySource方法
public class CustomClassPathXmlApplicationContext extends ClassPathXmlApplicationContext {
    public CustomClassPathXmlApplicationContext(String configLocation) throws BeansException {
        super(configLocation);
    }
    @Override
    protected void initPropertySources() {
        //给环境中设置name的属性值,validateProperty()方法中会进行判断
        getEnvironment().setRequiredProperties("name");
    }
}

//测试类方法
public class MainTest {
    public static void main(String[] args) {
        ClassPathXmlApplicationContext act = new CustomClassPathXmlApplicationContext("beans.xml");
    }
}

启动测试方法,会抛出错误异常,找不到name属性

Spring源码学习系列(四)之PostProcessor扩展点_第1张图片
错误异常堆栈

  • 刷新父容器BeanFactory,主要流程就是解析bean的配置信息,然后加载到BeanFactory里面,核心就是先获取一个DefaultListableBeanFactory,然后调用其loadBeanDefinitions进行加载bean的配置信息,和第一期的XmlBeanDefinitionReader.loadBeanDefinitions逻辑基本一致,并且这里也说明了ApplicationContext拥有BeanFactory父容器的所有功能。
    @Override
    protected final void refreshBeanFactory() throws BeansException {
        //如果之前有BeanFactory则清空
        if (hasBeanFactory()) {
            destroyBeans();
            closeBeanFactory();
        }
        try {
            DefaultListableBeanFactory beanFactory = createBeanFactory();
            beanFactory.setSerializationId(getId());
            //设置重复覆盖以及可循环依赖
            customizeBeanFactory(beanFactory);
            //加载所有的配置信息
            loadBeanDefinitions(beanFactory);
            synchronized (this.beanFactoryMonitor) {
                this.beanFactory = beanFactory;
            }
        }
    }
  • 为父容器做准备工作,添加了一些常用的组件,SpEl表达式解析器,类加载器,类型转化器等等。。
    protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
        // Tell the internal bean factory to use the context's class loader etc.
        //设置SpEl,ClassLoader,资源解析器等相关
        beanFactory.setBeanClassLoader(getClassLoader());
        beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
        beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));

        // Configure the bean factory with context callbacks.
        //设置后置处理器,该后置处理器的作用是给实现了Aware接口的实现类中的Spring组件赋值 ex : (BeanNameAware,ApplicationContextAware)
        beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
        //以及忽略注入(就是说这些被忽略的接口的实现类中的属性由Spring容器提供,不能自己注入)一些Spring容器中自带的Bean,
        beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
        beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
        beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
        beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
        beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
        beanFactory.ignoreDependencyInterface(ApplicationContextAware.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);

        // Register early post-processor for detecting inner beans as ApplicationListeners.
        beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));

        // Detect a LoadTimeWeaver and prepare for weaving, if found.
        //添加AspectJ的支持
        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());
        }
    }
  • 父容器初始化之后执行的逻辑,空实现,可在子类重载自定义增强实现
  • 执行BeanFactoryPostProcessor相关逻辑,方法申明如下,代码很多,可直接看总结
/**
     * 执行BeanFactoryPostProcessor及其子类BeanFactoryRegistryPostProcessor
     * @param beanFactory
     * @param beanFactoryPostProcessors
     */
    public static void invokeBeanFactoryPostProcessors(
            ConfigurableListableBeanFactory beanFactory, List beanFactoryPostProcessors) {

        // Invoke BeanDefinitionRegistryPostProcessors first, if any.
        Set processedBeans = new HashSet<>();
        //如果是BeanDefinitionRegistryPostProcessor类型的BeanFactoryPostProcessor会先执行其特有方法。
        // 否则添加到常规BeanFactoryPostProcessor中
        if (beanFactory instanceof BeanDefinitionRegistry) {
            BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
            List regularPostProcessors = new ArrayList<>();
            List registryProcessors = new ArrayList<>();
            for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
                //如果是BeanDefinitionRegistryPostProcessor则进入
                if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
                    BeanDefinitionRegistryPostProcessor registryProcessor =
                            (BeanDefinitionRegistryPostProcessor) postProcessor;
                    //会优先执行postProcessBeanDefinitionRegistry
                    registryProcessor.postProcessBeanDefinitionRegistry(registry);
                    registryProcessors.add(registryProcessor);
                }
                else {
                    regularPostProcessors.add(postProcessor);
                }
            }

            // Do not initialize FactoryBeans here: We need to leave all regular beans
            // uninitialized to let the bean factory post-processors apply to them!
            // Separate between BeanDefinitionRegistryPostProcessors that implement
            // PriorityOrdered, Ordered, and the rest.
            List currentRegistryProcessors = new ArrayList<>();

            // First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered.
            String[] postProcessorNames =
                    beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
            for (String ppName : postProcessorNames) {
                if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
                    currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
                    processedBeans.add(ppName);
                }
            }
            //1.对实现了PriorityOrdered接口的BeanDefinitionRegistryPostProcessor进行排序
            sortPostProcessors(currentRegistryProcessors, beanFactory);
            //注册到总的暂存容器中
            registryProcessors.addAll(currentRegistryProcessors);
            invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
            currentRegistryProcessors.clear();


            //2.然后对Order接口中的BeanDefinitionRegistryPostProcessor进行排序
            // Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered.
            postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
            for (String ppName : postProcessorNames) {
                if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {
                    currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
                    processedBeans.add(ppName);
                }
            }
            sortPostProcessors(currentRegistryProcessors, beanFactory);
            registryProcessors.addAll(currentRegistryProcessors);
            invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
            currentRegistryProcessors.clear();

            // Finally, invoke all other BeanDefinitionRegistryPostProcessors until no further ones appear.
            //3.最后将剩余的BeanDefinitionRegistryPostProcessor进行排序
            boolean reiterate = true;
            while (reiterate) {
                reiterate = false;
                postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
                for (String ppName : postProcessorNames) {
                    if (!processedBeans.contains(ppName)) {
                        currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
                        processedBeans.add(ppName);
                        reiterate = true;
                    }
                }
                sortPostProcessors(currentRegistryProcessors, beanFactory);
                registryProcessors.addAll(currentRegistryProcessors);
                invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
                currentRegistryProcessors.clear();
            }

            // Now, invoke the postProcessBeanFactory callback of all processors handled so far.
            invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);  //执行包括配置的和硬编码(通过addBeanFactoryPostProcessor添加的)的所有BeanFactoryRegistryPostProcessor的postProcessBeanFactory方法
            invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory); //执行硬编码中的BeanFactoryPostProcessor.postProcessBeanFactory
        }

        else {
            // Invoke factory processors registered with the context instance.
            //如果该工厂不是beanDefinitionRegistry则直接执行beanFactoryPostProcessor
            invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
        }

        // Do not initialize FactoryBeans here: We need to leave all regular beans
        // uninitialized to let the bean factory post-processors apply to them!
        String[] postProcessorNames =
                beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);

        // Separate between BeanFactoryPostProcessors that implement PriorityOrdered,
        // Ordered, and the rest.
        List priorityOrderedPostProcessors = new ArrayList<>();
        List orderedPostProcessorNames = new ArrayList<>();
        List nonOrderedPostProcessorNames = new ArrayList<>();
        for (String ppName : postProcessorNames) {
            if (processedBeans.contains(ppName)) {
                // skip - already processed in first phase above
            }
            else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
                priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
            }
            else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
                orderedPostProcessorNames.add(ppName);
            }
            else {
                nonOrderedPostProcessorNames.add(ppName);
            }
        }

        // First, invoke the BeanFactoryPostProcessors that implement PriorityOrdered.
        sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
        invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);

        // Next, invoke the BeanFactoryPostProcessors that implement Ordered.
        List orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());
        for (String postProcessorName : orderedPostProcessorNames) {
            orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
        }
        sortPostProcessors(orderedPostProcessors, beanFactory);
        invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);

        // Finally, invoke all other BeanFactoryPostProcessors.
        List nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());
        for (String postProcessorName : nonOrderedPostProcessorNames) {
            nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
        }
        invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);

        // Clear cached merged bean definitions since the post-processors might have
        // modified the original metadata, e.g. replacing placeholders in values...
        beanFactory.clearMetadataCache();
    }

总结来说有三点 :

  • BeanFactoryPostProcessor分两种 : 第一种是: BeanFactoryPostProcessor ,另外一种特殊的是 其子接口BeanFactoryRegistryPostProcessor,子接口的加载优先级高于BeanFactoryPostProcessor
  • BeanFactoryPostProcessor有两种来源,一种是'硬编码'也就是之前已经添加到AbstractApplicationContext.beanFactoryPostProcessors属性中的,可以通过AbstractApplicationContext.addBeanFactoryPostProcessor添加,另外一种是通过beanFactory解析类型配置的来获取beanFactory.getBeanNamesForType(),且'硬编码' 的优先级高于 ‘配置的’
  • 所有的后置处理器会按照PriorityOrdered > Order > 无序 的顺序进行执行

那么综上所述,总结源码的步骤如下

  • 先执行硬编码的BeanFactoryRegistry的特殊方法postProcessBeanDefinitionRegistry
  • 按排序顺序依次执行配置的BeanFactoryRegistryPostProcessor的特殊方法
  • 执行所有的BeanFactoryRegistryPostProcessorpostProcessBeanFactory()
  • 执行所有硬编码的非BeanFactoryRegistryPostProcessorpostProcessBeanFactory()方法
  • 执行是BeanFactoryRegistry但是非BeanFactoryRegistryPostProcessorpostProcessBeanFactory()方法
  • 依次按顺序执行配置的BeanFactoryPostProcessorpostProcessBeanFactory()
  • 最后删除元数据缓存
  • 注册所有的BeanPostProcessor,同理BeanFactoryPostProcessor,不过这里只是将所有配置中的BeanFactoryPostProcessor添加到beanFactory中,而在创建bean实例的时候才会执行,因为这里只是注册,所以不像BeanFactoryPostProcessor需要处理硬编码的部分。

  • 初始化国际化相关和事件派发器,这里比较简单,就是容器中没有然后会手动new一个添加到容器中

  • 扩展点,提供给子容器的刷新时机,比如与SpringMVC的父子容器

  • 注册ApplicationListener,会加载容器中所有的ApplicationListener,并使用上面初始化过的ApplicationEventMulticaster派发出去

  • 完成所有除后置处理相关的单实例bean的创建和初始化,主要通过getBean()方法来完成,具体可参考上一篇Bean的创建

public void preInstantiateSingletons() throws BeansException {
        if (logger.isTraceEnabled()) {
            logger.trace("Pre-instantiating singletons in " + this);
        }

        // Iterate over a copy to allow for init methods which in turn register new bean definitions.
        // While this may not be part of the regular factory bootstrap, it does otherwise work fine.
        List beanNames = new ArrayList<>(this.beanDefinitionNames);

        // Trigger initialization of all non-lazy singleton beans...
        for (String beanName : beanNames) {
            RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
            if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
                //如果是FactoryBean
                if (isFactoryBean(beanName)) {
                    Object bean = getBean(FACTORY_BEAN_PREFIX + beanName); //进入创建bean的流程,后置处理器也会生效
                    if (bean instanceof FactoryBean) {
                        final FactoryBean factory = (FactoryBean) bean;
                        boolean isEagerInit;
                        if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
                            isEagerInit = AccessController.doPrivileged((PrivilegedAction)
                                            ((SmartFactoryBean) factory)::isEagerInit,
                                    getAccessControlContext());
                        }
                        else {
                            isEagerInit = (factory instanceof SmartFactoryBean &&
                                    ((SmartFactoryBean) factory).isEagerInit());
                        }
                        if (isEagerInit) {
                            getBean(beanName);
                        }
                    }
                }
                else {
                    getBean(beanName);
                }
            }
        }

        // Trigger post-initialization callback for all applicable beans...
        //bean创建完对象后回调
        for (String beanName : beanNames) {
            Object singletonInstance = getSingleton(beanName);
            if (singletonInstance instanceof SmartInitializingSingleton) {
                final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
                if (System.getSecurityManager() != null) {
                    AccessController.doPrivileged((PrivilegedAction) () -> {
                        smartSingleton.afterSingletonsInstantiated();
                        return null;
                    }, getAccessControlContext());
                }
                else {
                    smartSingleton.afterSingletonsInstantiated();
                }
            }
        }
    }

  • 刷新之后的容器操作
        // Clear context-level resource caches (such as ASM metadata from scanning).
        clearResourceCaches();

        // Initialize lifecycle processor for this context.
                //初始化生命周期处理器
        initLifecycleProcessor();

        // Propagate refresh to lifecycle processor first.
        //设置生命周期状态为正在刷新
        getLifecycleProcessor().onRefresh();

        // Publish the final event.
        //发送正在刷新事件
        publishEvent(new ContextRefreshedEvent(this));

        // Participate in LiveBeansView MBean, if active.
        LiveBeansView.registerApplicationContext(this);

到此,refresh()方法和常用的后置处理的执行时机都整理完毕了。

你可能感兴趣的:(Spring源码学习系列(四)之PostProcessor扩展点)