Spring源码学习 | 2 ContextLoaderListener引导初始化Spring容器

前言

上一篇文章我们用一个demo来体验了Spring在web项目开发中的使用。并解释了Spring容器创建与初始化的位置。这一篇文章我们开始阅读代码,看看Spring容器创建、初始化的具体过程。

这篇文章里很多细枝末节并不会讲到,主要是想通过这篇文章,先了解、熟悉Spring容器的加载过程,脑子里对过程中有哪些步骤、步骤顺序等有一个全局的概念。正对一些值得深究的点,各点会有独立的文章。

背景知识

BeanFactory

比较早期的Spring Bean容器。接口中定义了作为Spring容器所要具备的方法、能力。

public interface BeanFactory {

	String FACTORY_BEAN_PREFIX = "&";

	Object getBean(String name) throws BeansException;

	<T> T getBean(String name, Class<T> requiredType) throws BeansException;

	Object getBean(String name, Object... args) throws BeansException;

	<T> T getBean(Class<T> requiredType) throws BeansException;

	<T> T getBean(Class<T> requiredType, Object... args) throws BeansException;

	<T> ObjectProvider<T> getBeanProvider(Class<T> requiredType);

	<T> ObjectProvider<T> getBeanProvider(ResolvableType requiredType);

	boolean containsBean(String name);

	boolean isSingleton(String name) throws NoSuchBeanDefinitionException;

	boolean isPrototype(String name) throws NoSuchBeanDefinitionException;

	boolean isTypeMatch(String name, ResolvableType typeToMatch) throws NoSuchBeanDefinitionException;

	boolean isTypeMatch(String name, Class<?> typeToMatch) throws NoSuchBeanDefinitionException;

	@Nullable
	Class<?> getType(String name) throws NoSuchBeanDefinitionException;

	@Nullable
	Class<?> getType(String name, boolean allowFactoryBeanInit) throws NoSuchBeanDefinitionException;

	String[] getAliases(String name);

}
复制代码

ApplicationContext

对BeanFactory的扩充,实现了BeanFactory所有功能,除了此以外,还具备资源解析、事件发布、消息等功能。有多重多样的实现类。是目前主流的Spring容器。

image.png

BeanDefinition

BeanDefinition是用来描述一个Bean的,直译过来就是Bean的定义。可以看到接口定义了各种方法来描述Bean的各种属性。Spring容器在初始化Bean的时候,不是直接从配置文件到Bean的,而是从配置文件解析为BeanDefinition,然后根据BeanDefinition实例化Bean。

public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {
	String SCOPE_SINGLETON = ConfigurableBeanFactory.SCOPE_SINGLETON;
	String SCOPE_PROTOTYPE = ConfigurableBeanFactory.SCOPE_PROTOTYPE;
	int ROLE_APPLICATION = 0;
	int ROLE_SUPPORT = 1;
	int ROLE_INFRASTRUCTURE = 2;

	void setParentName(@Nullable String parentName);

	@Nullable
	String getParentName();

	void setBeanClassName(@Nullable String beanClassName);

	@Nullable
	String getBeanClassName();

	void setScope(@Nullable String scope);

	@Nullable
	String getScope();

	void setLazyInit(boolean lazyInit);

	boolean isLazyInit();

	void setDependsOn(@Nullable String... dependsOn);

	@Nullable
	String[] getDependsOn();

	void setAutowireCandidate(boolean autowireCandidate);

	boolean isAutowireCandidate();

	void setPrimary(boolean primary);

	boolean isPrimary();

	void setFactoryBeanName(@Nullable String factoryBeanName);

	@Nullable
	String getFactoryBeanName();

	void setFactoryMethodName(@Nullable String factoryMethodName);

	@Nullable
	String getFactoryMethodName();

	ConstructorArgumentValues getConstructorArgumentValues();

	default boolean hasConstructorArgumentValues() {
		return !getConstructorArgumentValues().isEmpty();
	}

	MutablePropertyValues getPropertyValues();

	default boolean hasPropertyValues() {
		return !getPropertyValues().isEmpty();
	}

	void setInitMethodName(@Nullable String initMethodName);

	@Nullable
	String getInitMethodName();

	void setDestroyMethodName(@Nullable String destroyMethodName);

	@Nullable
	String getDestroyMethodName();

	void setRole(int role);

	int getRole();

	void setDescription(@Nullable String description);

	@Nullable
	String getDescription();

	ResolvableType getResolvableType();

	boolean isSingleton();

	boolean isPrototype();

	boolean isAbstract();

	@Nullable
	String getResourceDescription();

	@Nullable
	BeanDefinition getOriginatingBeanDefinition();

}
复制代码

BeanFactoryPostProcessor

针对BeanFactory的后置处理器。接口中只有一个方法,入参就是beanFactory。在postProcessBeanFactory()方法中可以对beanFactory进行各种修改。这是Spring对外提供的修改beanFactory的机会。实现了这个接口的类会在ApplicationContext实例化的过程中被调用,实现修改。

@FunctionalInterface
public interface BeanFactoryPostProcessor {
    void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;
}
复制代码

BeanPostProcessor

针对Bean的后置处理器。这是Spring对外提供的修改已实例化bean的机会。在bean初始化前、后各有一个回调方法,默认是不做任何操作,可以实现此接口,然后做自己想要的操作。

后置处理器机制在Spring中使用非常广泛。熟知的AOP就是利用了这个机制。

public interface BeanPostProcessor {
    @Nullable
    default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        return bean;
    }

    @Nullable
    default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        return bean;
    }
}
复制代码

FactoryBean

注意啊,这里是FactoryBean。不要和上面的搞混了。顾名思义,他本质应该是一个承担了工厂角色的Bean。看接口中最核心的方法就是getObject()。你实现接口并重写这个方法,就可以自由的创建你想要的的Bean实例。在Spring容器创建Bean的时候,也是使用了一个匿名的FactoryBean。

public interface FactoryBean<T> {
	String OBJECT_TYPE_ATTRIBUTE = "factoryBeanObjectType";

	@Nullable
	T getObject() throws Exception;

	@Nullable
	Class<?> getObjectType();

	default boolean isSingleton() {
		return true;
	}

}
复制代码

监听器引导初始化Spring容器

ServletContext初始化完成后,通知监听器。ContextLoaderListener进行Spring容器的初始化操作。主要逻辑在ContextLoader的initWebApplicationContext()方法完成。方法比较长,再次不做完整摘录。

获取容器类

获取容器类时,会先从servletContext中读取contextClass参数指定的类型;若无,则从ContextLoader类的defaultStrategies变量获取默认类名。

// ContextLoader类方法
protected Class<?> determineContextClass(ServletContext servletContext) {
    // 从servlet上下文获取配置的contextClass
    String contextClassName = servletContext.getInitParameter(CONTEXT_CLASS_PARAM);
    if (contextClassName != null) {
        try {
            return ClassUtils.forName(contextClassName, ClassUtils.getDefaultClassLoader());
        }
        catch (ClassNotFoundException ex) {
            throw new ApplicationContextException("Failed to load custom context class [" + contextClassName + "]", ex);
        }
    }
    else {
        // 读取默认的context的类名
        contextClassName = defaultStrategies.getProperty(WebApplicationContext.class.getName());
        try {
            return ClassUtils.forName(contextClassName, ContextLoader.class.getClassLoader());
        }
        catch (ClassNotFoundException ex) {
                throw new ApplicationContextException("Failed to load default context class [" + contextClassName + "]", ex);
        }
    }
}
复制代码

defaultStrategies的值是在ContextLoader类静态代码块中读取的。DEFAULT_STRATEGIES_PATH对应的值为ContextLoader.properties。

// ContextLoader类静态代码块
static {
    try {
        ClassPathResource resource = new ClassPathResource(DEFAULT_STRATEGIES_PATH, ContextLoader.class);
        defaultStrategies = PropertiesLoaderUtils.loadProperties(resource);
    }
    catch (IOException ex) {
        throw new IllegalStateException("Could not load 'ContextLoader.properties': " + ex.getMessage());
    }
}
复制代码

我们可以从spring-web包中找到这个ContextLoader.properties文件。其中只有一行内容,配置了Spring容器的类名。determineContextClass()方法根据类名返回对应的Class对象。

org.springframework.web.context.WebApplicationContext=org.springframework.web.context.support.XmlWebApplicationContext
复制代码

实例化容器

这一步没有特别的,就是使用BeanUtils.instantiateClass()方法,对上一步获取到的Class对象,选择默认构造函数,通过反射构造实例。最后会将类型强转为ConfigurableWebApplicationContext

设置父容器

然后会通过loadParentContext()方法获父容器,不过这个方法目前默认是返回null的。现在启动的其实就是Root WebApplicationContext,是没有父容器的。

注入获取配置文件位置

这里就是从servletContext获取配置文件位置,来源就是web.xml中context-parma配置的contextConfigLocation的值。

protected void configureAndRefreshWebApplicationContext(ConfigurableWebApplicationContext wac, ServletContext sc) {
    // 省略...
    // 从servletContext获取
    wac.setServletContext(sc);
    String configLocationParam = sc.getInitParameter(CONFIG_LOCATION_PARAM);
    if (configLocationParam != null) {
            wac.setConfigLocation(configLocationParam);
    }
    // 省略...
}
复制代码

customizeContext

这一步是,如果在web.xml配置了全局的或者上下文的初始化操作类,就会把这些类加载进来,排序并实例化,依次作用与刚创建的applicationContext。

refresh()刷新容器

这一步就是Spring容器比较关键的一步了。他会调用applicationContext的refresh方法。spring配置的读取、处理,spring bean的创建等等非常多的操作要在这一步。这一步也是需要着重学些的一步。下面会详细分析。

设置classloader

这一步是将ClassLoader与当前applicationContext以ConcurrentHashMap的显示存起来。

    ClassLoader ccl = Thread.currentThread().getContextClassLoader();
    if (ccl == ContextLoader.class.getClassLoader()) {
        currentContext = this.context;
    }
    else if (ccl != null) {
        // Map<ClassLoader, WebApplicationContext> currentContextPerThread = new ConcurrentHashMap<>(1);
        currentContextPerThread.put(ccl, this.context);
    }

复制代码

经过上述这些操作,一个完成的applicationContext就成功创建了。Spring也就在你的程序中顺利运转起来了。

Spring容器初始化流程

前面描述了ContextLoaderListener引导创建、初始化一个Spring容器applicationContext。Spring容器想要有那些强大的功能、能力,并不是创建之后就自然拥有的,而是做了大量的准备工作,来解析、处理等等各种复杂的操作。我们接下来就看下Spring容器是如何拥有这些能力的。

refresh()定义在ConfigurableApplicationContext接口中。

public interface ConfigurableApplicationContext extends ApplicationContext, Lifecycle, Closeable {

	String CONFIG_LOCATION_DELIMITERS = ",; \t\n";

	String CONVERSION_SERVICE_BEAN_NAME = "conversionService";

	String LOAD_TIME_WEAVER_BEAN_NAME = "loadTimeWeaver";

	String ENVIRONMENT_BEAN_NAME = "environment";

	String SYSTEM_PROPERTIES_BEAN_NAME = "systemProperties";

	String SYSTEM_ENVIRONMENT_BEAN_NAME = "systemEnvironment";

	String SHUTDOWN_HOOK_THREAD_NAME = "SpringContextShutdownHook";

	void setId(String id);

	void setParent(@Nullable ApplicationContext parent);

	void setEnvironment(ConfigurableEnvironment environment);

	@Override
	ConfigurableEnvironment getEnvironment();

	void addBeanFactoryPostProcessor(BeanFactoryPostProcessor postProcessor);

	void addApplicationListener(ApplicationListener<?> listener);

	void setClassLoader(ClassLoader classLoader);

	void addProtocolResolver(ProtocolResolver resolver);
        
        /**
	 * Load or refresh the persistent representation of the configuration, which
	 * might be from Java-based configuration, an XML file, a properties file, a
	 * relational database schema, or some other format.
	 * <p>As this is a startup method, it should destroy already created singletons
	 * if it fails, to avoid dangling resources. In other words, after invocation
	 * of this method, either all or no singletons at all should be instantiated.
	 * @throws BeansException if the bean factory could not be initialized
	 * @throws IllegalStateException if already initialized and multiple refresh
	 * attempts are not supported
	 */
	void refresh() throws BeansException, IllegalStateException;

	void registerShutdownHook();

	@Override
	void close();

	boolean isActive();

	ConfigurableListableBeanFactory getBeanFactory() throws IllegalStateException;

}

复制代码

前文说过,默认的容器类是XmlWebApplicationContext,我们在这个类中搜索,发现是他的父类AbstractApplicationContext实现了refresh()这个方法。

image.png

看到这个代码感觉非常简洁,所有步骤都封装成一个一个方法。这里是上一篇提到过的设计模式,模板方法模式。AbstractApplicationContext在refresh()方法中抽象了逻辑,规定了一些必须的步骤,同时提供方法给子类实现自己的逻辑。在保证所有子类的逻辑一致的情况下,又允许子类有不影响主逻辑的自定义逻辑。

public abstract class AbstractApplicationContext extends DefaultResourceLoader implements ConfigurableApplicationContext {
// 省略...

    @Override
    public void refresh() throws BeansException, IllegalStateException {
        // 同步处理
        synchronized (this.startupShutdownMonitor) {
            // 刷新前的一系列准备工作
            prepareRefresh();
            // 刷新并获取beanFactory,加载BeanDefinition
            ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
            // beanFactory的一些准备工作
            prepareBeanFactory(beanFactory);
            
            try {
                // 允许在这里对beanFactory进行个性化修改
                postProcessBeanFactory(beanFactory);
                // 执行BeanFactory后置处理器,修改beanFactory
                invokeBeanFactoryPostProcessors(beanFactory);
                // 注册Bean后置处理器
                registerBeanPostProcessors(beanFactory);
                // 消息、国际化相关
                initMessageSource();
                // 初始化多播(multicast)相关组件
                initApplicationEventMulticaster();
                // 子类实现个性化逻辑
                onRefresh();
                // 注册ApplicationListener监听器到上面的多播(multicast)相关组件
                registerListeners();
                // 实例化非懒加载的单例bean
                finishBeanFactoryInitialization(beanFactory);
                // 刷新收尾的一系列操作
                finishRefresh();
            }  catch (BeansException ex) {
                if (logger.isWarnEnabled()) {
                    logger.warn("Exception encountered during context initialization - " + "cancelling refresh attempt: " + ex);
                }
                destroyBeans();
                cancelRefresh(ex);
                throw ex;
            } finally {
                resetCommonCaches();
            }
        }
    }

// 省略...

}

复制代码

refresh()中各个方法大致的作用已经通过注释说明,接下来看看各个方法中具体做了什么。

prepareRefresh

这一步主要是准备工作,标志位修改啊,配置文件检查等操作,大致了解一下。

public abstract class AbstractApplicationContext extends DefaultResourceLoader implements ConfigurableApplicationContext {
    // 省略...

    protected void prepareRefresh() {
        this.startupDate = System.currentTimeMillis();
        this.closed.set(false);
        this.active.set(true);

        if (logger.isDebugEnabled()) {
            if (logger.isTraceEnabled()) {
                logger.trace("Refreshing " + this);
            }
            else {
                logger.debug("Refreshing " + getDisplayName());
            }
        }

        initPropertySources();
        getEnvironment().validateRequiredProperties();
        
        if (this.earlyApplicationListeners == null) {
            this.earlyApplicationListeners = new LinkedHashSet<>(this.applicationListeners);
        }
        else {
            this.applicationListeners.clear();
            this.applicationListeners.addAll(this.earlyApplicationListeners);
        }

        this.earlyApplicationEvents = new LinkedHashSet<>();
    }

    // 省略...
}

复制代码

obtainFreshBeanFactory

这个方法看起来很简短啊,而且顾名思义就两步:

  • 刷新BeanFactory
  • 获取并返回BeanFacotry
public abstract class AbstractApplicationContext extends DefaultResourceLoader implements ConfigurableApplicationContext {
// 省略...
    protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
        refreshBeanFactory();
        return getBeanFactory();
    }
// 省略...
}

复制代码

但是在refreshBeanFactory()方法中,其实会做不少事情。我们仍以默认的XmlWebApplicationContext为例,通过方法搜索,可以看到父类AbstractRefreshableApplicationContext实现了这个刷新BeanFactory的方法。

image.png

从代码看出,它的逻辑就是:如果已有beanFacotry实例,就先销毁;然后新建一个beanFactory对象并初始化。
这里有几个地方注意一下:

  • customizeBeanFactory():这个方法里设置beanFactory的allowCircularReferences属性,这个是用来控制是否允许循环依赖的。后面我们会讲到Spring的循环依赖,再详细讲。
  • loadBeanDefinitions():这个是读取、加载bean定义Bean定义的。注意,这里只是读取BeanDefinition,还没有进行实例化。 读取的方式有很多,比如xml、扫描注解等等,也由各子类自行实现。
public abstract class AbstractRefreshableApplicationContext extends AbstractApplicationContext {
    // 省略...
    
    @Override
    protected final void refreshBeanFactory() throws BeansException {
        if (hasBeanFactory()) {
            destroyBeans();
            closeBeanFactory();
        }
        try {
            DefaultListableBeanFactory beanFactory = createBeanFactory();
            beanFactory.setSerializationId(getId());
            // 对beanFactory客制化操作
            customizeBeanFactory(beanFactory);
            // 读取、解析Bean的定义
            loadBeanDefinitions(beanFactory);
            this.beanFactory = beanFactory;
        }
        catch (IOException ex) {
            throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
        }
    }
    
    // 省略...
}

复制代码

prepareBeanFactory

这个方法可以看到,全部是beanFactory.xxx()方法,是调整beanFactory各种设置的。

public abstract class AbstractApplicationContext extends DefaultResourceLoader implements ConfigurableApplicationContext {
    // 省略...
    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.getBeanClassLoader()));
        beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));

        // Configure the bean factory with context callbacks.
        beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
        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.
        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());
        }
    }
    // 省略...
}

复制代码

postProcessBeanFactory

这是一个空方法,由子类实现XmlWebApplicationContext的父类AbstractRefreshableWebApplicationContext实现了这个方法

image.png

简单看下

    /**
     * Register request/session scopes, a {@link ServletContextAwareProcessor}, etc.
     */
    @Override
    protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
        beanFactory.addBeanPostProcessor(new ServletContextAwareProcessor(this.servletContext, this.servletConfig));
        beanFactory.ignoreDependencyInterface(ServletContextAware.class);
        beanFactory.ignoreDependencyInterface(ServletConfigAware.class);

        WebApplicationContextUtils.registerWebApplicationScopes(beanFactory, this.servletContext);
        WebApplicationContextUtils.registerEnvironmentBeans(beanFactory, this.servletContext, this.servletConfig);
    }
复制代码

invokeBeanFactoryPostProcessors

这个方法主要逻辑在PostProcessorRegistrationDelegate类的invokeBeanFactoryPostProcessors()方法中。会寻找并执行BeanFactoryPostProcessor。具体的逻辑如下

  • 入参中的后置处理器区分BeanDefinitionRegistryPostProcessor、BeanFactoryPostProcessor
  • 寻找实现了PriorityOrdered接口的BeanDefinitionRegistryPostProcessor,排序后执行
  • 寻找实现了Ordered接口的BeanDefinitionRegistryPostProcessor,排序后执行
  • 寻找剩下的BeanDefinitionRegistryPostProcessor,排序后执行
  • 获取所有后置处理器,然后分类:已执行的、优先执行的、有序执行的、未排序的
  • 排序并执行优先执行的(实现了PriorityOrdered接口的)BeanFactoryPostProcessor
  • 排序并执行排序的(实现了Ordered接口的)BeanFactoryPostProcessor
  • 执行剩余的BeanFactoryPostProcessor
public static void invokeBeanFactoryPostProcessors(
                ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {
                
    Set<String> processedBeans = new HashSet<>();

    if (beanFactory instanceof BeanDefinitionRegistry) {
        BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
        List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
        List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();
        // 这里区分BeanDefinitionRegistryPostProcessor、BeanFactoryPostProcessor
        // 因为执行的顺序不一样
        for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
                if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
                        BeanDefinitionRegistryPostProcessor registryProcessor =
                                        (BeanDefinitionRegistryPostProcessor) postProcessor;
                        registryProcessor.postProcessBeanDefinitionRegistry(registry);
                        registryProcessors.add(registryProcessor);
                }
                else {
                        regularPostProcessors.add(postProcessor);
                }
        }

        List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();

        // 1. 寻找实现了PriorityOrdered接口的BeanDefinitionRegistryPostProcessor,排序后执行
        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);
            }
        }
        sortPostProcessors(currentRegistryProcessors, beanFactory);
        registryProcessors.addAll(currentRegistryProcessors);
        invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
        currentRegistryProcessors.clear();

        // 2. 寻找实现了Ordered接口的BeanDefinitionRegistryPostProcessor,排序后执行
        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();
        }
        // 执行剩余的BeanDefinitionRegistryPostProcessor
        invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
        // 执行入参带入的BeanFactoryPostProcessor
        invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
    }

    else {
        // 执行入参带入的后置处理器
        invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
    }

    // 获取所有后置处理器
    String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);

    List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
    List<String> orderedPostProcessorNames = new ArrayList<>();
    List<String> 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);
        }
    }

    // 排序并执行优先执行的(实现了PriorityOrdered接口的)BeanFactoryPostProcessor
    sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
    invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);

    // 排序并执行排序的(实现了Ordered接口的)BeanFactoryPostProcessor
    List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());
    for (String postProcessorName : orderedPostProcessorNames) {
        orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
    }
    sortPostProcessors(orderedPostProcessors, beanFactory);
    invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);

    // 执行剩余的BeanFactoryPostProcessor
    List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());
    for (String postProcessorName : nonOrderedPostProcessorNames) {
            nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
    }
    invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);

    beanFactory.clearMetadataCache();
}

复制代码

registerBeanPostProcessors

这个方法顾名思义就是注册BeanPostProcessor。主要逻辑是在PostProcessorRegistrationDelegate类的registerBeanPostProcessors()方法中。逻辑如下:

  • 获取并实例化所有BeanPostProcessor
  • 按PriorityOrdered、Ordered、其他 区分
  • 排序并注册实现了PriorityOrdered的BeanPostProcessor
  • 排序并注册实现了Ordered的BeanPostProcessor
  • 注册剩余BeanPostProcessor
  • 排序并注册MergedBeanDefinitionPostProcessor
  • 注册ApplicationListenerDetector(事件监听器的后置处理器)
public static void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {

    // 获取所有BeanPostProcessor名称
    String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);

    int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
    // 实例化BeanPostProcessor
    beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));

    // 按PriorityOrdered、Ordered、其他 区分
    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);
        }
    }

    // 1. 排序并注册实现了PriorityOrdered的BeanPostProcessor
    sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
    registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);

    // 2. 排序并注册实现了Ordered的BeanPostProcessor
    List<BeanPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());
    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);

    // 3. 注册剩余BeanPostProcessor
    List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());
    for (String ppName : nonOrderedPostProcessorNames) {
        BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
        nonOrderedPostProcessors.add(pp);
        if (pp instanceof MergedBeanDefinitionPostProcessor) {
            internalPostProcessors.add(pp);
        }
    }
    registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);

    // 4. 排序注册MergedBeanDefinitionPostProcessor。这个可能有注册过的再次注册
    sortPostProcessors(internalPostProcessors, beanFactory);
    registerBeanPostProcessors(beanFactory, internalPostProcessors);

    // 注册ApplicationListenerDetector(事件监听器的后置处理器),保持在处理器链最后
    beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
}
复制代码

initMessageSource

消息、国际化相关,暂时先略过不讲。= =

initApplicationEventMulticaster

这里主要是实例化一个applicationEventMulticaster,application事件多播器(= =是这样翻译么)。用来支持ApplicationContext实现的ApplicationEventPublisher接口的事件发布功能。暂时先略过不讲。= =

onRefresh

空方法,子类实现个性化逻辑,暂时先略过不讲。= =

registerListeners

这个方法就是在applicationEventMulticaster(前面刚提到的)上注册事件监听器。简单看下。

插句题外话,观察到一个现象,很多方法都是先处理ApplicationContext中的成员变量,然后再分局类型获取创建实例,再对获取到的实例分类处理。看invokeBeanFactoryPostProcessors()、registerBeanPostProcessors()还有当前这一段代码,都有这个特点。那么联想到,我们其实是可以对ApplicationContext中的内容自定义修改然后refresh()的。= =

public abstract class AbstractApplicationContext extends DefaultResourceLoader implements ConfigurableApplicationContext {
    // 省略...
    protected void registerListeners() {
        for (ApplicationListener<?> listener : getApplicationListeners()) {
            getApplicationEventMulticaster().addApplicationListener(listener);
        }

        String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
        for (String listenerBeanName : listenerBeanNames) {
            getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
        }
        
        Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
        this.earlyApplicationEvents = null;
        if (!CollectionUtils.isEmpty(earlyEventsToProcess)) {
            for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
                getApplicationEventMulticaster().multicastEvent(earlyEvent);
            }
        }
    }
    // 省略...
}

复制代码

finishBeanFactoryInitialization

这里可以说是Spring容器初始化最重要的一步。在这一步中,会把所有非懒加载的单例对象都实例化,交给容器管理。这一块的内容可能比较多。这里先简单说一下Bean实例化步骤,以后写一篇文章详谈。

  • 实例化
  • 属性填充
  • BeanNameAware、BeanFactoryAware、ApplicationContextAware
  • BeanPostProcessor.postProcessBeforeInitialization
  • @PostConstruct
  • InitializationBean
  • init-method
  • BeanPostProcessor.postProcessAfterInitialization

finishRefresh

主要是refresh收尾的操作。暂时先略过不讲。= =

public abstract class AbstractApplicationContext extends DefaultResourceLoader implements ConfigurableApplicationContext {
// 省略...
    protected void finishRefresh() {
        clearResourceCaches();
        initLifecycleProcessor();
        getLifecycleProcessor().onRefresh();
        publishEvent(new ContextRefreshedEvent(this));
        LiveBeansView.registerApplicationContext(this);
    }
// 省略...
}
复制代码

结语

这一篇文章写的非常的长了,用一张图来总结一下吧。本文只是对ContextLoaderListener引导初始化Spring容器的流程做了了一些梳理,希望自己对这个过程熟悉,特别是refresh()方法,然后再深入看流程中的重要步骤。

ClassPathXmlApplicationContext (1).jpg

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享