Spring

Spring IOC源码解析(11)Bean加载过程

2020-06-19  本文已影响0人  juconcurrent

前言

前面我们分析了spring ioc边缘化的很多组件,这些组件是分析Bean加载过程的基石。基石可理解成下面的意思:

  1. 基石是高层的基础
  2. 基石可以有很多种,这些基石相互组合、继承、扩展,从而延伸出更多高级的功能
  3. 单独的基石只能完成某一部分相对独立的功能,它不是完整的
  4. 基石很重要,但是基石的堆砌更重要(即:架构设计的思维)

Spring IOC最核心的功能在于Bean加载过程,也是最能体现架构设计高度的一块内容。网上有很多这方面的分析文章,在借鉴了这些前辈经验的基础上,楼主还是想将源码阅读的过程记录下来,并最终对其进行分析总结。

开篇,一个最简单的入门级例子

Spring IOC容器管理的两个类。

public interface MessageService {
    String getMessage();
}

public class MessageServiceImpl implements MessageService {
    public String getMessage() {
        return "hello world";
    }
}

xml配置信息。

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

    <bean id="messageService" class="com.juconcurrent.learn.spring.MessageServiceImpl"/>
</beans>

如何使用?

public class Main {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("classpath:application.xml");
        MessageService messageService = context.getBean(MessageService.class);
        System.out.println(messageService.getMessage());
    }
}

输出结果:

hello world

从上面的例子我们看到,Spring IOC有两个口子供我们分析:

  1. ClassPathXmlApplicationContext()构造方法
  2. context.getBean()方法

构造器

先来看看构造方法,其主要做了以下事情:

  1. 配置的位置可转换成多个(即:数组),默认为一个
  2. refresh参数表示是否自动刷新上下文,默认刷新
  3. parent表示父context,默认没有
/**
 * Create a new ClassPathXmlApplicationContext, loading the definitions
 * from the given XML file and automatically refreshing the context.
 * @param configLocation resource location
 * @throws BeansException if context creation failed
 */
public ClassPathXmlApplicationContext(String configLocation) throws BeansException {
    this(new String[] {configLocation}, true, null);
}

/**
 * Create a new ClassPathXmlApplicationContext with the given parent,
 * loading the definitions from the given XML files.
 * @param configLocations array of resource locations
 * @param refresh whether to automatically refresh the context,
 * loading all bean definitions and creating all singletons.
 * Alternatively, call refresh manually after further configuring the context.
 * @param parent the parent context
 * @throws BeansException if context creation failed
 * @see #refresh()
 */
public ClassPathXmlApplicationContext(
        String[] configLocations, boolean refresh, @Nullable ApplicationContext parent)
        throws BeansException {

    super(parent);
    setConfigLocations(configLocations);
    if (refresh) {
        refresh();
    }
}

我们一直点super(parent),看到最内部的实现如下:

public abstract class AbstractApplicationContext {
    public AbstractApplicationContext(@Nullable ApplicationContext parent) {
        // 设置解析资源文件的策略类对象,可解析多种类型的资源文件,
        // 默认实现为`PathMatchingResourcePatternResolver`。
        this();
        // 设置父容器,在父容器不为空的情况下,父容器的`Environment`即被继承过来。
        setParent(parent);
    }
    
    public AbstractApplicationContext() {
        this.resourcePatternResolver = getResourcePatternResolver();
    }
    
    protected ResourcePatternResolver getResourcePatternResolver() {
        return new PathMatchingResourcePatternResolver(this);
    }
    
    public void setParent(@Nullable ApplicationContext parent) {
        this.parent = parent;
        if (parent != null) {
            Environment parentEnvironment = parent.getEnvironment();
            if (parentEnvironment instanceof ConfigurableEnvironment) {
                getEnvironment().merge((ConfigurableEnvironment) parentEnvironment);
            }
        }
    }
}

接下来看看setConfigLocations()

/**
 * 设置配置的位置。如果不设置,就是空的。
 * Set the config locations for this application context.
 * <p>If not set, the implementation may use a default as appropriate.
 */
public void setConfigLocations(@Nullable String... locations) {
    if (locations != null) {
        Assert.noNullElements(locations, "Config locations must not be null");
        this.configLocations = new String[locations.length];
        for (int i = 0; i < locations.length; i++) {
            // 这儿会使用`Environment`进行路径解析,
            // 默认的实现为`StandardEnvironment`。
            this.configLocations[i] = resolvePath(locations[i]).trim();
        }
    }
    else {
        this.configLocations = null;
    }
}

protected String resolvePath(String path) {
    return getEnvironment().resolveRequiredPlaceholders(path);
}

public ConfigurableEnvironment getEnvironment() {
    if (this.environment == null) {
        this.environment = createEnvironment();
    }
    return this.environment;
}

protected ConfigurableEnvironment createEnvironment() {
    return new StandardEnvironment();
}

refresh方法

核心的代码在于refresh()方法。之所以命名成refresh,而不是init之类的方法,有以下几个原因:

  1. 该方法方法可反复调用
  2. 在配置变动之后,可通过该方法进行重新加载(也就是热加载)
  3. refresh英文名为刷新,正符合当前的语境

接下来,我们分析一下这个方法。

public void refresh() throws BeansException, IllegalStateException {
    // 先来一个锁,避免并发刷新的问题
    synchronized (this.startupShutdownMonitor) {
        // 为刷新而准备上下文
        // Prepare this context for refreshing.
        prepareRefresh();

        // 告诉子类刷新内部的bean工厂,主要做了以下几件事:
        // 1. 如果存在bean工厂,则先销毁其管理的所有bean,并关闭工厂
        // 2. 创建新的bean工厂
        // 3. 加载BeanDefinitions
        // Tell the subclass to refresh the internal bean factory.
        ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

        // 准备在上下文中使用这个bean工厂
        // Prepare the bean factory for use in this context.
        prepareBeanFactory(beanFactory);

        try {
            // 允许子类重写此方法,以便增加bean工厂创建后的逻辑。默认什么都不做。
            // Allows post-processing of the bean factory in context subclasses.
            postProcessBeanFactory(beanFactory);

            // 调用bean工厂的后置处理器,这些处理器前面已经注册到了上下文
            // Invoke factory processors registered as beans in the context.
            invokeBeanFactoryPostProcessors(beanFactory);

            // 注册bean后置处理器,在bean的创建过程中会被调用
            // Register bean processors that intercept bean creation.
            registerBeanPostProcessors(beanFactory);

            // 初始化消息源
            // Initialize message source for this context.
            initMessageSource();

            // 初始化上下文中的事件广播器
            // Initialize event multicaster for this context.
            initApplicationEventMulticaster();

            // 初始化其他的特殊Bean
            // Initialize other special beans in specific context subclasses.
            onRefresh();

            // 检查并注册监听器bean
            // Check for listener beans and register them.
            registerListeners();

            // 实例化所有剩下的`non-lazy-init`单例
            // Instantiate all remaining (non-lazy-init) singletons.
            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();

            // 重置active标记为false
            // 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();
        }
    }
}

这个方法包含了Spring IOC容器初始化的所有操作步骤。当我们读懂了每一行代码,就意味着我们了解了Spring IOC的所有功能。虽然该方法只有寥寥十多行,但是当下钻到每个方法的内部,我们就会发现其调用层级之深,简直令人发指,不过这并不能阻碍我们的钻研。接下来,我们将深入分析每个方法内部的逻辑。

prepareRefresh方法

该方法用于准备上下文。

/**
 * Prepare this context for refreshing, setting its startup date and
 * active flag as well as performing any initialization of property sources.
 */
protected void prepareRefresh() {
    // Switch to active.
    // 设置开始时间,设置关闭标记为false,设置激活标记为true
    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());
        }
    }

    // 在上下文环境中,初始化属性源(例如:将带占位符的属性源进行替换),
    // 默认为空实现。
    // Initialize any placeholder property sources in the context environment.
    initPropertySources();

    // 在Environment中,校验所有需要的属性(如果那些标注为必需的属性不存在的话,将抛出异常)
    // Validate that all properties marked as required are resolvable:
    // see ConfigurablePropertyResolver#setRequiredProperties
    getEnvironment().validateRequiredProperties();

    // 存储(或者叫设置)预刷新的应用监听器,需要注意以下两点:
    // 1. 如果`earlyApplicationListeners`不为空,说明用户自定义过,那么将不需要使用`applicationListeners`进行覆盖
    // 2. 如果`earlyApplicationListeners`为空,说明用户未自定义过,那么需要根据`applicationListeners`进行设置
    // Store pre-refresh ApplicationListeners...
    if (this.earlyApplicationListeners == null) {
        this.earlyApplicationListeners = new LinkedHashSet<>(this.applicationListeners);
    }
    else {
        // Reset local application listeners to pre-refresh state.
        this.applicationListeners.clear();
        this.applicationListeners.addAll(this.earlyApplicationListeners);
    }

    // 设置初始的早期应用事件
    // Allow for the collection of early ApplicationEvents,
    // to be published once the multicaster is available...
    this.earlyApplicationEvents = new LinkedHashSet<>();
}

根据上面的源码,我们知道这个方法主要做了以下几件事情:

  1. 设置开始时间和激活标记;
  2. 校验所有需要的属性
  3. 初始化应用监听器及应用事件

obtainFreshBeanFactory方法

该方法用于获取一个新鲜的bean工厂。那么,何为新鲜?

  1. 如果已经存在一个bean工厂的话,需要先将其销毁并关闭
  2. 创建一个新的bean工厂

那么其内部具体是怎么实现的呢?我们来分析下obtainFreshBeanFactory()方法。

/**
 * 先刷新,后获取。
 * Tell the subclass to refresh the internal bean factory.
 * @return the fresh BeanFactory instance
 * @see #refreshBeanFactory()
 * @see #getBeanFactory()
 */
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
    refreshBeanFactory();
    return getBeanFactory();
}

refreshBeanFactory()方法:

/**
 * This implementation performs an actual refresh of this context's underlying
 * bean factory, shutting down the previous bean factory (if any) and
 * initializing a fresh bean factory for the next phase of the context's lifecycle.
 */
@Override
protected final void refreshBeanFactory() throws BeansException {
    // 如果bean工厂存在,那么销毁所有的单例bean,并且关闭bean工厂
    if (hasBeanFactory()) {
        destroyBeans();
        closeBeanFactory();
    }
    try {
        // 创建bean工厂
        DefaultListableBeanFactory beanFactory = createBeanFactory();
        // 设置序列id
        beanFactory.setSerializationId(getId());
        // 自定义bean工厂
        customizeBeanFactory(beanFactory);
        // 加载BeanDefinitions
        loadBeanDefinitions(beanFactory);
        // 设置bean工厂
        synchronized (this.beanFactoryMonitor) {
            this.beanFactory = beanFactory;
        }
    }
    catch (IOException ex) {
        throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
    }
}

接下来我们分析下refreshBeanFactory()方法内部调用的方法,这些方法除了loadBeanDefinitions()比较复杂,其他都很简单。

销毁相关的方法如下:

/**
 * Determine whether this context currently holds a bean factory,
 * i.e. has been refreshed at least once and not been closed yet.
 */
protected final boolean hasBeanFactory() {
    synchronized (this.beanFactoryMonitor) {
        return (this.beanFactory != null);
    }
}

// 从这儿看出只是销毁了所有的单例bean,其他scope的bean并没有被销毁
protected void destroyBeans() {
    getBeanFactory().destroySingletons();
}

// 关闭bean工厂,就是将bean工厂设置为null
protected final void closeBeanFactory() {
    synchronized (this.beanFactoryMonitor) {
        if (this.beanFactory != null) {
            this.beanFactory.setSerializationId(null);
            this.beanFactory = null;
        }
    }
}

createBeanFactory()方法,内部其实就是一个DefaultListableBeanFactory的实例。

protected DefaultListableBeanFactory createBeanFactory() {
    return new DefaultListableBeanFactory(getInternalParentBeanFactory());
}

customizeBeanFactory方法,选择性地设置了两个参数:

  1. 允许bean定义被覆盖
  2. 允许循环依赖
protected void customizeBeanFactory(DefaultListableBeanFactory beanFactory) {
    if (this.allowBeanDefinitionOverriding != null) {
        beanFactory.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
    }
    if (this.allowCircularReferences != null) {
        beanFactory.setAllowCircularReferences(this.allowCircularReferences);
    }
}

由于我们分析的入口是ClassPathXmlApplicationContext,因此Spring IOC管理的bean是从xml中加载过来的。我们分析的loadBeanDefinitions()方法,其内部应该也是如此。

最后有一个赋值语句this.beanFactory = beanFactory;,这说明ApplicationContext和BeanFactory的关系,最终还是组合的关系,这样的好处就是松耦合,并且方便后续扩展和维护。

loadBeanDefinitions()

/**
 * Loads the bean definitions via an XmlBeanDefinitionReader.
 * @see org.springframework.beans.factory.xml.XmlBeanDefinitionReader
 * @see #initBeanDefinitionReader
 * @see #loadBeanDefinitions
 */
@Override
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
    // 通过bean工厂,实例化一个`XmlBeanDefinitionReader`,表示xml下BeanDefinition的读取器
    // Create a new XmlBeanDefinitionReader for the given BeanFactory.
    XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);

    // 配置bean定义读取器,包括:环境对象、资源加载器、资源实体处理器
    // Configure the bean definition reader with this context's
    // resource loading environment.
    beanDefinitionReader.setEnvironment(this.getEnvironment());
    beanDefinitionReader.setResourceLoader(this);
    beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));

    // Allow a subclass to provide custom initialization of the reader,
    // then proceed with actually loading the bean definitions.
    // 初始化
    initBeanDefinitionReader(beanDefinitionReader);
    // 加载
    loadBeanDefinitions(beanDefinitionReader);
}

initBeanDefinitionReader()用于初始化操作,主要设置校验开关。

  1. 当校验的时候,校验模式设置为自动
  2. 当不校验的时候,校验模式设置为“不校验”,同时设置命名空间验证,这样的话,就从侧面进行了验证。
protected void initBeanDefinitionReader(XmlBeanDefinitionReader reader) {
    reader.setValidating(this.validating);
}
/**
 * Set whether to use XML validation. Default is {@code true}.
 * <p>This method switches namespace awareness on if validation is turned off,
 * in order to still process schema namespaces properly in such a scenario.
 * @see #setValidationMode
 * @see #setNamespaceAware
 */
public void setValidating(boolean validating) {
    this.validationMode = (validating ? VALIDATION_AUTO : VALIDATION_NONE);
    this.namespaceAware = !validating;
}

重载的loadBeanDefinitions()方法传入参数为reader。

protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
    Resource[] configResources = getConfigResources();
    if (configResources != null) {
        reader.loadBeanDefinitions(configResources);
    }
    String[] configLocations = getConfigLocations();
    if (configLocations != null) {
        reader.loadBeanDefinitions(configLocations);
    }
}

从上面的代码我们看出,xml配置加载的方式有两种,一种是以通用资源的方式,另一种是以配置位置的方式。配置位置的方式,最终将转换为通用资源的方式。接下来,我们分析下配置位置的方式。

public int loadBeanDefinitions(String... locations) throws BeanDefinitionStoreException {
    Assert.notNull(locations, "Location array must not be null");
    int count = 0;
    for (String location : locations) {
        count += loadBeanDefinitions(location);
    }
    return count;
}

public int loadBeanDefinitions(String location) throws BeanDefinitionStoreException {
    return loadBeanDefinitions(location, null);
}

/**
 * Load bean definitions from the specified resource location.
 * <p>The location can also be a location pattern, provided that the
 * ResourceLoader of this bean definition reader is a ResourcePatternResolver.
 * @param location the resource location, to be loaded with the ResourceLoader
 * (or ResourcePatternResolver) of this bean definition reader
 * @param actualResources a Set to be filled with the actual Resource objects
 * that have been resolved during the loading process. May be {@code null}
 * to indicate that the caller is not interested in those Resource objects.
 * @return the number of bean definitions found
 * @throws BeanDefinitionStoreException in case of loading or parsing errors
 * @see #getResourceLoader()
 * @see #loadBeanDefinitions(org.springframework.core.io.Resource)
 * @see #loadBeanDefinitions(org.springframework.core.io.Resource[])
 */
public int loadBeanDefinitions(String location, @Nullable Set<Resource> actualResources) throws BeanDefinitionStoreException {
    ResourceLoader resourceLoader = getResourceLoader();
    if (resourceLoader == null) {
        throw new BeanDefinitionStoreException(
                "Cannot load bean definitions from location [" + location + "]: no ResourceLoader available");
    }

    if (resourceLoader instanceof ResourcePatternResolver) {
        // Resource pattern matching available.
        try {
            // 关键的代码在这儿,通过资源加载器将配置位置转换成了通用资源。
            Resource[] resources = ((ResourcePatternResolver) resourceLoader).getResources(location);
            int count = loadBeanDefinitions(resources);
            if (actualResources != null) {
                Collections.addAll(actualResources, resources);
            }
            if (logger.isTraceEnabled()) {
                logger.trace("Loaded " + count + " bean definitions from location pattern [" + location + "]");
            }
            return count;
        }
        catch (IOException ex) {
            throw new BeanDefinitionStoreException(
                    "Could not resolve bean definition resource pattern [" + location + "]", ex);
        }
    }
    else {
        // Can only load single resources by absolute URL.
        Resource resource = resourceLoader.getResource(location);
        int count = loadBeanDefinitions(resource);
        if (actualResources != null) {
            actualResources.add(resource);
        }
        if (logger.isTraceEnabled()) {
            logger.trace("Loaded " + count + " bean definitions from location [" + location + "]");
        }
        return count;
    }
}

通用资源的BeanDefinition加载过程非常地复杂,因为xml配置支持的标签非常多。限于篇幅,本文不做深入的分析。

在阅读源码的时候,楼主发现BeanDefinition有好几个实现类,如下所示。我们着重分析红框内的类。

图片.png

他们的区别大致是这样的。

RootBeanDefinition是最常用的实现类,它对应一般性的<bean>元素标签,GenericBeanDefinition是自2.5以后新加入的bean文件配置属性定义类,是一站式服务类。在配置文件中可以定义父<bean>子<bean>父<bean>RootBeanDefinition表示,而子<bean>ChildBeanDefiniton表示,而没有父<bean><bean>就使用RootBeanDefinition表示。AbstractBeanDefinition对两者共同的类信息进行了抽象。

prepareBeanFactory方法

用于设置一些bean工厂相关的信息。例如:

  1. bean的类加载器、表达式处理、属性编辑器注册器
  2. 手动添加了一些bean后置处理器
  3. 指定某些依赖接口不被spring ioc容器所管理
  4. 手动注入一些关键的bean,例如bean工厂、应用上下文、环境相关的bean等等
/**
 * Configure the factory's standard context characteristics,
 * such as the context's ClassLoader and post-processors.
 * @param beanFactory the BeanFactory to configure
 */
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
    // Tell the internal bean factory to use the context's class loader etc.
    // 设置bean的类加载器
    beanFactory.setBeanClassLoader(getClassLoader());
    // 设置bean的表达式处理器
    beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
    // 设置属性编辑器注册器
    beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));

    // Configure the bean factory with context callbacks.
    // 添加bean后置处理器,用于给管理的bean设置“应用上下文”
    beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
    // 忽略依赖接口,凡是继承这些接口的类实例将不会被spring ioc容器管理
    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`、`ResourceLoader`、`ApplicationEventPublisher`和`ApplicationContext`。
    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.
    // 添加bean后置处理器,用于探测内部bean
    beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));

    // Detect a LoadTimeWeaver and prepare for weaving, if found.
    // 添加bean后置处理器,用于AOP运行时织入
    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.
    // 注册一些默认的环境相关的单例bean
    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方法

该方法用于bean工厂加载后的后置处理,默认为空实现。

/**
 * 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 registering special
 * BeanPostProcessors etc in certain ApplicationContext implementations.
 * @param beanFactory the bean factory used by the application context
 */
protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
}

invokeBeanFactoryPostProcessors方法

该方法用于调用bean工厂的后置处理器(已注册的)。

/**
 * Instantiate and invoke all registered BeanFactoryPostProcessor beans,
 * respecting explicit order if given.
 * <p>Must be called before singleton instantiation.
 */
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
    PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());

    // Detect a LoadTimeWeaver and prepare for weaving, if found in the meantime
    // (e.g. through an @Bean method registered by ConfigurationClassPostProcessor)
    // 运行时切面织入相关的配置
    if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
        beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
        beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
    }
}

PostProcessorRegistrationDelegate是一个工具类,其下的invokeBeanFactoryPostProcessors方法非常复杂。为啥会这么复杂,主要是由于以下几个方面:

  1. BeanFactoryPostProcessor可以被配置;
  2. BeanFactoryPostProcessor有一个特殊的子类BeanDefinitionRegistryPostProcessor,其用途就是方便BeanFactoryPostProcessor可以灵活地配置;
  3. BeanFactoryPostProcessor可以定义优先级顺序性,以及无顺序性

接下来,我们具体看看源代码。

// 该类是final修饰,说明其不可继承。同时其构造器是私有的,说明不能被实例化。因此其就是一个静态工具类。
final class PostProcessorRegistrationDelegate {

    private PostProcessorRegistrationDelegate() {
    }

    public static void invokeBeanFactoryPostProcessors(
            ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {

        // Invoke BeanDefinitionRegistryPostProcessors first, if any.
        Set<String> processedBeans = new HashSet<>();

        // 因为beanFactory的默认实现为`DefaultListableBeanFactory`,所以本身就继承了`BeanDefinitionRegistry`。
        // 这儿,我们仅分析if语句块就可以了。
        if (beanFactory instanceof BeanDefinitionRegistry) {
            // bean工厂就是`BeanDefinitionRegistry`
            BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
            // 分离出标准的后置处理器,以及注册器后置处理器
            List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
            List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();

            for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
                if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
                    BeanDefinitionRegistryPostProcessor registryProcessor =
                            (BeanDefinitionRegistryPostProcessor) postProcessor;
                    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.
            // 1. 工厂bean不会被实例化
            // 2. 优先处理注册器后置处理器
            List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();

            // First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered.
            // 第一步,处理实现了`PriorityOrdered`接口的`BeanDefinitionRegistryPostProcessor`,包括:
            // 1. 排序
            // 2. 添加到`registryProcessors`,方便后续统一处理
            // 3. 调用`postProcessBeanDefinitionRegistry`方法
            // 4. 清理currentRegistryProcessors,方便后续复用
            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();

            // Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered.
            // 第二步,处理实现了`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.
            // 最终,调用所有除了实现`PriorityOrdered`和`Ordered`的`BeanDefinitionRegistryPostProcessors`,
            // 处理步骤和第一步相同
            // 注意,这儿使用了while循环,而不是if,楼主也不知道是为什么
            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.
            // OK,上面的都做完了,就可以开始调用bean工厂的后置处理器了
            invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
            invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
        }

        else {
            // Invoke factory processors registered with the context instance.
            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!
        // 除了上面的bean工厂后置处理器,我们还可以自己配置一些bean工厂后置处理器,例如:
        // 1. 在xml中通过<bean>的方式
        // 2. 在java config中通过@Bean的方式
        // 3. 在自动装配中通过@Componet的方式
        // 因此,在这儿我们需要对这些后置处理器进行处理。
        // 同样地,根据是否是`PriorityOrdered`、`Ordered`,会有特殊的处理。
        String[] postProcessorNames =
                beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);

        // Separate between BeanFactoryPostProcessors that implement PriorityOrdered,
        // Ordered, and the rest.
        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);
            }
        }

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

        // Next, invoke the BeanFactoryPostProcessors that implement Ordered.
        List<BeanFactoryPostProcessor> 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<BeanFactoryPostProcessor> 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();
    }
}

registerBeanPostProcessors方法

该方法用于注册bean后置处理器,最终调用的仍然是PostProcessorRegistrationDelegate中的工具方法,我们来看一下。

protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) {
    PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this);
}

public static void registerBeanPostProcessors(
        ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {

    String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);

    // Register BeanPostProcessorChecker that logs an info message when
    // a bean is created during BeanPostProcessor instantiation, i.e. when
    // a bean is not eligible for getting processed by all BeanPostProcessors.
    // 这儿会做两件事情:
    // 1. 统计bean后置处理器的个数,格式是根据以下地方进行统计的
    //     1. bean工厂内部的
    //     2. 随后添加的一个检查bean后置处理器
    //     3. 用户自己定义的
    // 2. 添加一个bean后置处理器,用于检查目的,当检查不通过时,将记录info级别的日志
    int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
    beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));

    // Separate between BeanPostProcessors that implement PriorityOrdered,
    // Ordered, and the rest.
    // 分离出`PriorityOrdered`、`Ordered`和剩下的bean后置处理器
    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);
        }
    }

    // First, register the BeanPostProcessors that implement PriorityOrdered.
    // 第一步,排序并重新注册到bean工厂(PriorityOrdered)
    sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
    registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);

    // Next, register the BeanPostProcessors that implement Ordered.
    // 第二步,排序并重新注册到bean工厂(Ordered)
    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);

    // Now, register all regular BeanPostProcessors.
    // 第三步,注册剩余的到bean工厂
    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);

    // Finally, re-register all internal BeanPostProcessors.
    // 最后一步,重新注册内部的到bean工厂,目的是将他们排序到最后位置
    sortPostProcessors(internalPostProcessors, beanFactory);
    registerBeanPostProcessors(beanFactory, internalPostProcessors);

    // Re-register post-processor for detecting inner beans as ApplicationListeners,
    // moving it to the end of the processor chain (for picking up proxies etc).
    // 添加一个事件监听的bean后置处理器,但是不纳入bean后置处理器个数的统计
    beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
}

initMessageSource方法

该方法用于初始化消息源。所谓消息源,是为了支持国际化而服务的,本文我们不会过多地对此进行分析。

initApplicationEventMulticaster方法

该方法用于初始化应用事件广播器。

/**
 * Initialize the ApplicationEventMulticaster.
 * Uses SimpleApplicationEventMulticaster if none defined in the context.
 * @see org.springframework.context.event.SimpleApplicationEventMulticaster
 */
protected void initApplicationEventMulticaster() {
    ConfigurableListableBeanFactory beanFactory = getBeanFactory();
    // 如果bean工厂包含应用事件广播器,那么就使用它
    // 否则,使用`SimpleApplicationEventMulticaster`创建一个默认的应用事件广播器
    if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {
        this.applicationEventMulticaster =
                beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);
        if (logger.isTraceEnabled()) {
            logger.trace("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]");
        }
    }
    else {
        this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
        beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);
        if (logger.isTraceEnabled()) {
            logger.trace("No '" + APPLICATION_EVENT_MULTICASTER_BEAN_NAME + "' bean, using " +
                    "[" + this.applicationEventMulticaster.getClass().getSimpleName() + "]");
        }
    }
}

onRefresh方法

该方法用于初始化其他特殊的bean,默认为空实现

registerListeners方法

用于注册应用监听器到应用事件广播器中。

/**
 * Add beans that implement ApplicationListener as listeners.
 * Doesn't affect other listeners, which can be added without being beans.
 */
protected void registerListeners() {
    // Register statically specified listeners first.
    // 注册静态的监听器
    for (ApplicationListener<?> listener : getApplicationListeners()) {
        getApplicationEventMulticaster().addApplicationListener(listener);
    }

    // Do not initialize FactoryBeans here: We need to leave all regular beans
    // uninitialized to let post-processors apply to them!
    // 注册自定义的监听器
    String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
    for (String listenerBeanName : listenerBeanNames) {
        getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
    }

    // Publish early application events now that we finally have a multicaster...
    // 对预设置的事件进行广播
    Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
    this.earlyApplicationEvents = null;
    if (earlyEventsToProcess != null) {
        for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
            getApplicationEventMulticaster().multicastEvent(earlyEvent);
        }
    }
}

finishBeanFactoryInitialization方法

用于实例化所有剩余的非懒加载的单例bean。

/**
 * Finish the initialization of this context's bean factory,
 * initializing all remaining singleton beans.
 */
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
    // Initialize conversion service for this context.
    // 初始化转换服务
    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));
    }

    // Register a default embedded value resolver if no bean post-processor
    // (such as a PropertyPlaceholderConfigurer bean) registered any before:
    // at this point, primarily for resolution in annotation attribute values.
    // 如果没有嵌套值处理器,那么注册一个默认的嵌套值处理器
    if (!beanFactory.hasEmbeddedValueResolver()) {
        beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));
    }

    // Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early.
    // 初始化运行时织入的bean
    String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
    for (String weaverAwareName : weaverAwareNames) {
        getBean(weaverAwareName);
    }

    // Stop using the temporary ClassLoader for type matching.
    // 停止临时的类加载器
    beanFactory.setTempClassLoader(null);

    // Allow for caching all bean definition metadata, not expecting further changes.
    // 冻结配置(即:配置不可再被修改)
    beanFactory.freezeConfiguration();

    // Instantiate all remaining (non-lazy-init) singletons.
    // 调用工厂方法`preInstantiateSingletons`,预实例化所有的单例bean。
    // 该方法非常关键,其内部解决循环依赖问题的思路非常有意思。
    beanFactory.preInstantiateSingletons();
}

preInstantiateSingletons方法

该方法用于初始化所有的单例bean,其最最核心和关键的内容在于使用三级缓存解决循环依赖的问题。

那么,Spring为什么能解决循环依赖的问题呢?网上有很多这方面的分析,各种前因后果,细细道来冗长而繁琐。

为了便于理解,楼主直接说结果。能解决的根本原因在于引用传递。对象初始化之后,其引用就已经确定下来了,后期也不会再变化,因此引用可以被其他地方使用。我们可以将初始化的过程分成两个阶段:

  1. 构造器创建对象(创建a对象,传播b对象)
  2. 设置依赖关系(给a对象设置b对象引用,给b对象设置a对象引用)

在此基础上,Spring衍生出了三级缓存,其仅支持单例的循环依赖。

  1. 不能解决的情况:
    1. 构造器注入循环依赖
    2. prototype field属性注入(或者setter方法注入)循环依赖
  2. 能解决的情况:
    1. field属性注入(或者setter方法注入)循环依赖

好了,步入正轨,我们开始分析这个方法。

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.
    // bean定义的名称,就是bean的名称
    List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);

    // Trigger initialization of all non-lazy singleton beans...
    for (String beanName : beanNames) {
        // 合并bean定义
        RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
        // 只有非抽象的、单例的、非懒加载的bean定义,才会实例化成bean,并注册到bean工厂
        if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
            // 1. 如果是工厂bean,同时为预加载的话,那么直接调用`getBean`方法加载bean
            // 2. 如果不是工厂bean,直接调用`getBean`方法加载bean
            if (isFactoryBean(beanName)) {
                Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
                if (bean instanceof FactoryBean) {
                    final FactoryBean<?> factory = (FactoryBean<?>) bean;
                    boolean isEagerInit;
                    if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
                        isEagerInit = AccessController.doPrivileged((PrivilegedAction<Boolean>)
                                        ((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加载之后,如果bean为`SmartInitializingSingleton`类型,那么将触发方法`afterSingletonsInstantiated()`
    for (String beanName : beanNames) {
        Object singletonInstance = getSingleton(beanName);
        if (singletonInstance instanceof SmartInitializingSingleton) {
            final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
            if (System.getSecurityManager() != null) {
                AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
                    smartSingleton.afterSingletonsInstantiated();
                    return null;
                }, getAccessControlContext());
            }
            else {
                smartSingleton.afterSingletonsInstantiated();
            }
        }
    }
}

getBean()方法至关重要,用于获取一个bean。其调用的是doGetBean()方法,根据名称获取一个bean。

public Object getBean(String name) throws BeansException {
    return doGetBean(name, null, null, false);
}

接下来,我们分析一下doGetBean()方法。

/**
 * Return an instance, which may be shared or independent, of the specified bean.
 * @param name the name of the bean to retrieve
 * @param requiredType the required type of the bean to retrieve
 * @param args arguments to use when creating a bean instance using explicit arguments
 * (only applied when creating a new instance as opposed to retrieving an existing one)
 * @param typeCheckOnly whether the instance is obtained for a type check,
 * not for actual use
 * @return an instance of the bean
 * @throws BeansException if the bean could not be created
 */
@SuppressWarnings("unchecked")
protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
        @Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {

    // 获取bean最初的名称,因为传入的bean名称可能是一个别名,也可能是一个工厂bean的名称
    final String beanName = transformedBeanName(name);
    Object bean;

    // Eagerly check singleton cache for manually registered singletons.
    // 这儿尝试从三级缓存获取单例对象
    Object sharedInstance = getSingleton(beanName);
    if (sharedInstance != null && args == null) {
        if (logger.isTraceEnabled()) {
            if (isSingletonCurrentlyInCreation(beanName)) {
                logger.trace("Returning eagerly cached instance of singleton bean '" + beanName +
                        "' that is not fully initialized yet - a consequence of a circular reference");
            }
            else {
                logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
            }
        }
        // 从三级缓存获取到之后,将尝试将bean手动注册到bean工厂
        bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
    }

    else {
        // Fail if we're already creating this bean instance:
        // We're assumably within a circular reference.
        // 如果三级缓存没获取到,且bean为prototype类型,那么抛出异常
        if (isPrototypeCurrentlyInCreation(beanName)) {
            throw new BeanCurrentlyInCreationException(beanName);
        }

        // Check if bean definition exists in this factory.
        // 如果当前bean工厂不包含bean的定义,则委托给父工厂进行get处理
        BeanFactory parentBeanFactory = getParentBeanFactory();
        if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
            // Not found -> check parent.
            String nameToLookup = originalBeanName(name);
            if (parentBeanFactory instanceof AbstractBeanFactory) {
                return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
                        nameToLookup, requiredType, args, typeCheckOnly);
            }
            else if (args != null) {
                // Delegation to parent with explicit args.
                return (T) parentBeanFactory.getBean(nameToLookup, args);
            }
            else if (requiredType != null) {
                // No args -> delegate to standard getBean method.
                return parentBeanFactory.getBean(nameToLookup, requiredType);
            }
            else {
                return (T) parentBeanFactory.getBean(nameToLookup);
            }
        }

        // 如果不仅仅是类型检查,那么将beanName放入已创建的bean名称集合里面
        if (!typeCheckOnly) {
            markBeanAsCreated(beanName);
            // 这就是上面方法的实现
            /*
            protected void markBeanAsCreated(String beanName) {
                if (!this.alreadyCreated.contains(beanName)) {
                    synchronized (this.mergedBeanDefinitions) {
                        if (!this.alreadyCreated.contains(beanName)) {
                            // Let the bean definition get re-merged now that we're actually creating
                            // the bean... just in case some of its metadata changed in the meantime.
                            clearMergedBeanDefinition(beanName);
                            this.alreadyCreated.add(beanName);
                        }
                    }
                }
            }
            */
        }

        try {
            // 获取合并的bean定义,并检查(这儿判断是否为abstract)
            final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
            checkMergedBeanDefinition(mbd, beanName, args);

            // Guarantee initialization of beans that the current bean depends on.
            // 这儿会判断是否存在构造器的循环依赖,如果存在则抛出异常,否则的话就先注册依赖关系,再get这个bean
            String[] dependsOn = mbd.getDependsOn();
            if (dependsOn != null) {
                for (String dep : dependsOn) {
                    if (isDependent(beanName, dep)) {
                        throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                                "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
                    }
                    registerDependentBean(dep, beanName);
                    try {
                        getBean(dep);
                    }
                    catch (NoSuchBeanDefinitionException ex) {
                        throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                                "'" + beanName + "' depends on missing bean '" + dep + "'", ex);
                    }
                }
            }

            // Create bean instance.
            // 创建单例
            if (mbd.isSingleton()) {
                // 创建单例的时候,会传入一个ObjectFactory的对象。首先它是一个工厂,然后他会创一个对象。
                sharedInstance = getSingleton(beanName, () -> {
                    try {
                        return createBean(beanName, mbd, args);
                    }
                    catch (BeansException ex) {
                        // Explicitly remove instance from singleton cache: It might have been put there
                        // eagerly by the creation process, to allow for circular reference resolution.
                        // Also remove any beans that received a temporary reference to the bean.
                        destroySingleton(beanName);
                        throw ex;
                    }
                });
                // 获取到bean的时候,为啥不直接返回,原因在于获取到的bean可能是一个工厂bean,工厂bean又可能是工厂bean的工厂bean。
                // 因此,这个方法就是解决这个问题而存在的。
                bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
            }
            
            // 创建prototype
            else if (mbd.isPrototype()) {
                // It's a prototype -> create a new instance.
                Object prototypeInstance = null;
                try {
                    beforePrototypeCreation(beanName);
                    prototypeInstance = createBean(beanName, mbd, args);
                }
                finally {
                    afterPrototypeCreation(beanName);
                }
                bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
            }

            // 创建其他Scope
            else {
                String scopeName = mbd.getScope();
                final Scope scope = this.scopes.get(scopeName);
                if (scope == null) {
                    throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
                }
                try {
                    Object scopedInstance = scope.get(beanName, () -> {
                        beforePrototypeCreation(beanName);
                        try {
                            return createBean(beanName, mbd, args);
                        }
                        finally {
                            afterPrototypeCreation(beanName);
                        }
                    });
                    bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
                }
                catch (IllegalStateException ex) {
                    throw new BeanCreationException(beanName,
                            "Scope '" + scopeName + "' is not active for the current thread; consider " +
                            "defining a scoped proxy for this bean if you intend to refer to it from a singleton",
                            ex);
                }
            }
        }
        catch (BeansException ex) {
            cleanupAfterBeanCreationFailure(beanName);
            throw ex;
        }
    }

    // Check if required type matches the type of the actual bean instance.
    // 如果类型不匹配,则需要通过转换器进行转换。当转换不成功,则抛出异常。
    if (requiredType != null && !requiredType.isInstance(bean)) {
        try {
            T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);
            if (convertedBean == null) {
                throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
            }
            return convertedBean;
        }
        catch (TypeMismatchException ex) {
            if (logger.isTraceEnabled()) {
                logger.trace("Failed to convert bean '" + name + "' to required type '" +
                        ClassUtils.getQualifiedName(requiredType) + "'", ex);
            }
            throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
        }
    }
    return (T) bean;
}

重点来了!

在分析完doGetBean()方法后,我们发现不管是当前bean,还是依赖的bean,最终调用的都是getSingleton()方法。该方法有好几个重载方法,我们依次来分析。

/** Cache of singleton objects: bean name to bean instance. */
// 一级缓存,缓存已实例化的bean
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);

/** Cache of early singleton objects: bean name to bean instance. */
// 二级缓存,缓存`early`(可提前暴露)的bean
private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);

/** Cache of singleton factories: bean name to ObjectFactory. */
// 三级缓存,缓存对象工厂对象
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);

/** Set of registered singletons, containing the bean names in registration order. */
// 已注册的单例bean名称
private final Set<String> registeredSingletons = new LinkedHashSet<>(256);

/** Names of beans that are currently in creation. */
// 当前正在创建的单例bean名称
private final Set<String> singletonsCurrentlyInCreation =
        Collections.newSetFromMap(new ConcurrentHashMap<>(16));

// 调用的是下面那个方法,且参数`allowEarlyReference`为true
public Object getSingleton(String beanName) {
    return getSingleton(beanName, true);
}

protected Object getSingleton(String beanName, boolean allowEarlyReference) {
    // 1. 先从一级缓存`singletonObjects`中去获取。(如果获取到就直接return)
    Object singletonObject = this.singletonObjects.get(beanName);
    if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
        synchronized (this.singletonObjects) {
            // 2. 如果获取不到或者对象正在创建中(isSingletonCurrentlyInCreation()),那就再从二级缓存earlySingletonObjects中获取。(如果获取到就直接return)
            singletonObject = this.earlySingletonObjects.get(beanName);
            if (singletonObject == null && allowEarlyReference) {
                // 3. 如果还是获取不到,且允许`singletonFactories`(`allowEarlyReference = true`)通过`getObject()`获取。
                // 就从三级缓存`singletonFactory.getObject()`获取。
                // (如果获取到了就从`singletonFactories`中移除,并且放进`earlySingletonObjects`。
                // 其实也就是从三级缓存移动(是剪切、不是复制哦~)到了二级缓存)
                ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
                if (singletonFactory != null) {
                    singletonObject = singletonFactory.getObject();
                    this.earlySingletonObjects.put(beanName, singletonObject);
                    this.singletonFactories.remove(beanName);
                }
            }
        }
    }
    return singletonObject;
}

/**
 * 相比较于上个方法,多了错误校验、异常处理、外置化`ObjectFactory`创建对象的操作。
 * Return the (raw) singleton object registered under the given name,
 * creating and registering a new one if none registered yet.
 * @param beanName the name of the bean
 * @param singletonFactory the ObjectFactory to lazily create the singleton
 * with, if necessary
 * @return the registered singleton object
 */
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
    Assert.notNull(beanName, "Bean name must not be null");
    synchronized (this.singletonObjects) {
        Object singletonObject = this.singletonObjects.get(beanName);
        if (singletonObject == null) {
            if (this.singletonsCurrentlyInDestruction) {
                throw new BeanCreationNotAllowedException(beanName,
                        "Singleton bean creation not allowed while singletons of this factory are in destruction " +
                        "(Do not request a bean from a BeanFactory in a destroy method implementation!)");
            }
            if (logger.isDebugEnabled()) {
                logger.debug("Creating shared instance of singleton bean '" + beanName + "'");
            }
            beforeSingletonCreation(beanName);
            boolean newSingleton = false;
            boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
            if (recordSuppressedExceptions) {
                this.suppressedExceptions = new LinkedHashSet<>();
            }
            try {
                singletonObject = singletonFactory.getObject();
                newSingleton = true;
            }
            catch (IllegalStateException ex) {
                // Has the singleton object implicitly appeared in the meantime ->
                // if yes, proceed with it since the exception indicates that state.
                singletonObject = this.singletonObjects.get(beanName);
                if (singletonObject == null) {
                    throw ex;
                }
            }
            catch (BeanCreationException ex) {
                if (recordSuppressedExceptions) {
                    for (Exception suppressedException : this.suppressedExceptions) {
                        ex.addRelatedCause(suppressedException);
                    }
                }
                throw ex;
            }
            finally {
                if (recordSuppressedExceptions) {
                    this.suppressedExceptions = null;
                }
                afterSingletonCreation(beanName);
            }
            if (newSingleton) {
                addSingleton(beanName, singletonObject);
            }
        }
        return singletonObject;
    }
}

简单总结一下,Spring解决循环依赖的三级缓存逻辑如下:

  1. 先从一级缓存singletonObjects中去获取。(如果获取到就直接return)
  2. 如果获取不到或者对象正在创建中(isSingletonCurrentlyInCreation()),那就再从二级缓存earlySingletonObjects中获取。(如果获取到就直接return)
  3. 如果还是获取不到,且允许singletonFactoriesallowEarlyReference = true)通过getObject()获取。就从三级缓存singletonFactory.getObject()获取。(如果获取到了就从singletonFactories中移除,并且放进earlySingletonObjects。其实也就是从三级缓存移动(是剪切、不是复制哦~)到了二级缓存)。

生命周期

在分析finishRefresh()方法之前,我们有必要澄清一下,何为生命周期?

所谓生命周期,其实是一系列的回调。包括:

  1. Initialization callbacks(初始化回调)
  2. Destruction callbacks(销毁回调)

要与容器的bean生命周期管理交互,即容器在启动后和容器在销毁前对每个bean执行操作,有如下三种方法:

  1. 实现Spring框架的InitializingBeanDisposableBean接口。容器为前者调用afterPropertiesSet()方法,为后者调用destroy()方法,以允许bean在初始化和销毁的时候执行某些操作。
public class HelloLifeCycle implements InitializingBean, DisposableBean {
    
    public void afterPropertiesSet() throws Exception {
        System.out.println("afterPropertiesSet 启动");
    }

    public void destroy() throws Exception {
        System.out.println("DisposableBean 停止");
    }
}
  1. 在xml配置中,bean在定义的时候,指定初始化方法和销毁方法。
 <bean id="helloLifeCycle" class="com.hzways.life.cycle.HelloLifeCycle" init-method="init3" destroy-method="destroy3"/>
  1. JSR-250中,@PostConstruct@PreDestroy注解,可用于bean的初始化后和销毁前操作。
@Service
public class HelloLifeCycle {

    @PostConstruct
    private void init2() {
        System.out.println("PostConstruct 启动");
    }

    @PreDestroy
    private void destroy2() {
        System.out.println("PreDestroy 停止");
    }
}

finishRefresh方法

该方法主要调用了生命周期处理器的onRefresh()方法。

/**
 * Finish the refresh of this context, invoking the LifecycleProcessor's
 * onRefresh() method and publishing the
 * {@link org.springframework.context.event.ContextRefreshedEvent}.
 */
protected void finishRefresh() {
    // 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.
    // MBean管理相关
    LiveBeansView.registerApplicationContext(this);
}

这儿我们着重关注两个方法:initLifecycleProcessor()getLifecycleProcessor().onRefresh()

initLifecycleProcessor方法

该方法很简单。

  1. 首先尝试从bean工厂获取生命周期处理器;
  2. 如果bean工厂未获取到,初始化一个默认的生命周期处理器(DefaultLifecycleProcessor),并注册到bean工厂;
  3. 在前面两部的基础上,设置处理到AbstractApplicationContext的成员变量lifecycleProcessor上,供后续使用。
/**
 * Initialize the LifecycleProcessor.
 * Uses DefaultLifecycleProcessor if none defined in the context.
 * @see org.springframework.context.support.DefaultLifecycleProcessor
 */
protected void initLifecycleProcessor() {
    ConfigurableListableBeanFactory beanFactory = getBeanFactory();
    if (beanFactory.containsLocalBean(LIFECYCLE_PROCESSOR_BEAN_NAME)) {
        this.lifecycleProcessor =
                beanFactory.getBean(LIFECYCLE_PROCESSOR_BEAN_NAME, LifecycleProcessor.class);
        if (logger.isTraceEnabled()) {
            logger.trace("Using LifecycleProcessor [" + this.lifecycleProcessor + "]");
        }
    }
    else {
        DefaultLifecycleProcessor defaultProcessor = new DefaultLifecycleProcessor();
        defaultProcessor.setBeanFactory(beanFactory);
        this.lifecycleProcessor = defaultProcessor;
        beanFactory.registerSingleton(LIFECYCLE_PROCESSOR_BEAN_NAME, this.lifecycleProcessor);
        if (logger.isTraceEnabled()) {
            logger.trace("No '" + LIFECYCLE_PROCESSOR_BEAN_NAME + "' bean, using " +
                    "[" + this.lifecycleProcessor.getClass().getSimpleName() + "]");
        }
    }
}

onRefresh方法

分析该方法前,先看看getLifecycleProcessor(),其实就是检查并返回成员变量lifecycleProcessor

LifecycleProcessor getLifecycleProcessor() throws IllegalStateException {
    if (this.lifecycleProcessor == null) {
        throw new IllegalStateException("LifecycleProcessor not initialized - " +
                "call 'refresh' before invoking lifecycle methods via the context: " + this);
    }
    return this.lifecycleProcessor;
}
public void onRefresh() {
    startBeans(true);
    this.running = true;
}

onRefresh()方法调用了startBeans方法,之后更新了运行状态。

private void startBeans(boolean autoStartupOnly) {
    // 获取所有Bean工厂管理的`Lifecycle`对象
    Map<String, Lifecycle> lifecycleBeans = getLifecycleBeans();
    Map<Integer, LifecycleGroup> phases = new HashMap<>();
    // 根据`phase`进行分组
    lifecycleBeans.forEach((beanName, bean) -> {
        if (!autoStartupOnly || (bean instanceof SmartLifecycle && ((SmartLifecycle) bean).isAutoStartup())) {
            int phase = getPhase(bean);
            LifecycleGroup group = phases.get(phase);
            if (group == null) {
                group = new LifecycleGroup(phase, this.timeoutPerShutdownPhase, lifecycleBeans, autoStartupOnly);
                phases.put(phase, group);
            }
            group.add(beanName, bean);
        }
    });
    // 根据分组,调用对象的`start()`方法
    if (!phases.isEmpty()) {
        List<Integer> keys = new ArrayList<>(phases.keySet());
        Collections.sort(keys);
        for (Integer key : keys) {
            phases.get(key).start();
        }
    }
}

startBeans()方法做了以下事情:

  1. 首先获取所有Bean工厂管理的Lifecycle对象;
  2. Lifecycle对象根据phase(阶段的意思,其实是一个int值)进行分组。相同phase的对象划到一个组;
  3. 根据phase的值大小,升序调用其Lifecycle对象的start()方法。

getLifecycleBeans()方法用于获取对象。

/**
 * Retrieve all applicable Lifecycle beans: all singletons that have already been created,
 * as well as all SmartLifecycle beans (even if they are marked as lazy-init).
 * @return the Map of applicable beans, with bean names as keys and bean instances as values
 */
protected Map<String, Lifecycle> getLifecycleBeans() {
    ConfigurableListableBeanFactory beanFactory = getBeanFactory();
    Map<String, Lifecycle> beans = new LinkedHashMap<>();
    // 获取所有类型为`Lifecycle`的bean名称
    String[] beanNames = beanFactory.getBeanNamesForType(Lifecycle.class, false, false);
    for (String beanName : beanNames) {
        String beanNameToRegister = BeanFactoryUtils.transformedBeanName(beanName);
        boolean isFactoryBean = beanFactory.isFactoryBean(beanNameToRegister);
        String beanNameToCheck = (isFactoryBean ? BeanFactory.FACTORY_BEAN_PREFIX + beanName : beanName);
        // 这儿对bean加了一些限制条件
        // 1. 如果是单例的话,不能是工厂bean,且类型必须为`Lifecycle`
        // 2. 如果不是单例的话,类型必须为`SmartLifecycle`
        if ((beanFactory.containsSingleton(beanNameToRegister) &&
                (!isFactoryBean || matchesBeanType(Lifecycle.class, beanNameToCheck, beanFactory))) ||
                matchesBeanType(SmartLifecycle.class, beanNameToCheck, beanFactory)) {
            Object bean = beanFactory.getBean(beanNameToCheck);
            if (bean != this && bean instanceof Lifecycle) {
                beans.put(beanNameToRegister, (Lifecycle) bean);
            }
        }
    }
    return beans;
}

最关键的地方在于start()方法的调用。

public void start() {
    if (this.members.isEmpty()) {
        return;
    }
    if (logger.isDebugEnabled()) {
        logger.debug("Starting beans in phase " + this.phase);
    }
    // 对分组内的bean按照名称进行排序,并最终调用了`doStart()`方法
    Collections.sort(this.members);
    for (LifecycleGroupMember member : this.members) {
        doStart(this.lifecycleBeans, member.name, this.autoStartupOnly);
    }
}

/**
 * Start the specified bean as part of the given set of Lifecycle beans,
 * making sure that any beans that it depends on are started first.
 * @param lifecycleBeans a Map with bean name as key and Lifecycle instance as value
 * @param beanName the name of the bean to start
 */
private void doStart(Map<String, ? extends Lifecycle> lifecycleBeans, String beanName, boolean autoStartupOnly) {
    Lifecycle bean = lifecycleBeans.remove(beanName);
    if (bean != null && bean != this) {
        String[] dependenciesForBean = getBeanFactory().getDependenciesForBean(beanName);
        for (String dependency : dependenciesForBean) {
            // 这儿有递归调用。
            // 需要特别注意的地方在于,如果一个`Lifecycle`依赖另外一个`Lifecycle`,则会优先调用被依赖的`Lifecycle`。
            doStart(lifecycleBeans, dependency, autoStartupOnly);
        }
        if (!bean.isRunning() &&
                (!autoStartupOnly || !(bean instanceof SmartLifecycle) || ((SmartLifecycle) bean).isAutoStartup())) {
            if (logger.isTraceEnabled()) {
                logger.trace("Starting bean '" + beanName + "' of type [" + bean.getClass().getName() + "]");
            }
            try {
                // 庐山真面目,最终调到了`Lifecycle`的`start`方法。
                bean.start();
            }
            catch (Throwable ex) {
                throw new ApplicationContextException("Failed to start bean '" + beanName + "'", ex);
            }
            if (logger.isDebugEnabled()) {
                logger.debug("Successfully started bean '" + beanName + "'");
            }
        }
    }
}

至此,onRefresh()方法分析完成。

destroyBeans方法

该方法用于销毁bean,内部调用的是bean工厂的destroySingletons()方法。【注意】:这儿仅销毁了单例bean!

总结

我们从源码层面分析了bean加载的整个过程,每个步骤各司其职,环环相扣,非常地精彩。其中最显眼的地方在于Spring对bean循环依赖的解决方案(三级缓存)。

借鉴于网上的一张图,bean加载的过程如下所示:

而这张图标绿的地方,单独解释如下:

除此之外,我们还需要关注一下bean的生命周期,这是贯穿Spring IOC的一条主线。

  1. 实例化bean
  2. 设置属性值
  3. 调用BeanNameAware.setBeanName()方法
  4. 调用BeanFactoryAware.setBeanFactory()方法
  5. 调用BeanPostProcessor.postProcessBeforeInitialization()方法
    1. 调用ApplicationContextAware.setApplicationContext()方法
    2. 调用@PostConstruct所在的方法
    3. 其他...
  6. 调用InitializingBean.afterPropertiesSet()方法
  7. 调用init方法
  8. 调用BeanPostProcessor.postProcessAfterInitialization()方法
  9. 调用DisposableBean.destroy()方法
  10. 调用destory方法

参考文档

  1. https://blog.csdn.net/nuomizhende45/article/details/81158383
  2. https://www.jianshu.com/p/9ea61d204559
  3. https://www.cnblogs.com/lqmblog/p/8592817.html
  4. https://www.jianshu.com/p/e4ca039a2272
  5. https://www.jianshu.com/p/a6a03d94d6f7
  6. https://www.jianshu.com/p/43b65ed2e166
  7. https://blog.csdn.net/f641385712/article/details/92801300
上一篇下一篇

猜你喜欢

热点阅读