Spring5IOC容器解析——refresh()方法分析

Spring容器创建之后,会调用它的refresh方法刷新Spring应用的上下文。

首先整体查看AbstractApplicationContext#refresh源码

/**
 * 加载或刷新一个持久化的配置,可能是XML文件、属性文件或关系数据库模式。
 * 由于这是一种启动方法,如果失败,应该销毁已经创建的单例,以避免悬空资源。
 * 换句话说,在调用该方法之后,要么全部实例化,要么完全不实例化。
 * @throws BeansException 如果bean工厂无法初始化,则抛出 BeansException 异常
 * @throws IllegalStateException 如果已经初始化且不支持多次刷新,则会抛出 IllegalStateException 异常
 */
@Override
public void refresh() throws BeansException, IllegalStateException {
    // 给容器refresh加锁,避免容器处在refresh阶段时,容器进行了初始化或者销毁的操作
    synchronized (this.startupShutdownMonitor) {
        // Prepare this context for refreshing.
        // 调用容器准备刷新的方法,获取容器的当时时间,同时给容器设置同步标识,具体方法
        prepareRefresh();

        // Tell the subclass to refresh the internal bean factory.
        //告诉子类启动refreshBeanFactory()方法,Bean定义资源文件的载入从
        //子类的refreshBeanFactory()方法启动,里面有抽象方法
        //针对xml配置,最终创建内部容器,该容器负责 Bean 的创建与管理,此步会进行BeanDefinition的注册
        ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

        // Prepare the bean factory for use in this context.
        // 注册一些容器中需要的系统Bean.例如classloader,beanfactoryPostProcessor等
        prepareBeanFactory(beanFactory);

        try {
            // Allows post-processing of the bean factory in context subclasses.
            //允许容器的子类去注册postProcessor  ,钩子方法
            postProcessBeanFactory(beanFactory);

            // Invoke factory processors registered as beans in the context.
            // 激活在容器中注册为bean的BeanFactoryPostProcessors
            //对于注解容器,org.springframework.context.annotation.ConfigurationClassPostProcessor#postProcessBeanDefinitionRegistry
            //方法扫描应用中所有BeanDefinition并注册到容器之中
            invokeBeanFactoryPostProcessors(beanFactory);

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

            // Initialize message source for this context.
            // 找到“messageSource”的Bean提供给ApplicationContext使用,
            // 使得ApplicationContext具有国际化能力。
            initMessageSource();

            // Initialize event multicaster for this context.
            // 初始化ApplicationEventMulticaster该类作为事件发布者,
            // 可以存储所有事件监听者信息,并根据不同的事件,通知不同的事件监听者。
            initApplicationEventMulticaster();

            // Initialize other special beans in specific context subclasses.
            // 预留给 AbstractApplicationContext 的子类用于初始化其他特殊的 bean,
            // 该方法需要在所有单例 bean 初始化之前调用
            // 比如Web容器就会去初始化一些和主题展示相关的Bean(ThemeSource)
            onRefresh();

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

            // Instantiate all remaining (non-lazy-init) singletons.
            //设置自定义的类型转化器ConversionService,
            // 设置自定义AOP相关的类LoadTimeWeaverAware,
            // 清除临时的ClassLoader
            // ,实例化所有的类(懒加载的类除外)
            finishBeanFactoryInitialization(beanFactory);

            // Last step: publish corresponding event.
            // 初始化容器的生命周期事件处理器,(默认使用DefaultLifecycleProcessor),调用扩展了SmartLifecycle接口的start方法
            // 当Spring容器加载所有bean并完成初始化之后,会接着回调实现该接口的类中对应的方法(start()方法)
            // 并发布容器刷新完毕事件ContextRefreshedEvent给对应的事件监听者
            finishRefresh();
        }

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

            // Destroy already created singletons to avoid dangling resources.
            //销毁已创建的Bean
            destroyBeans();

            // Reset 'active' flag.
            //取消refresh操作,重置容器的同步标识
            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...
            // 重置Spring内核中的共用的缓存,因为我们可能再也不需要单例bean的元数据了……
            resetCommonCaches();
        }
    }
}

prepareRefresh()方法

// 准备这个上下文来刷新、设置它的启动日期和活动标志以及执行属性源的任何初始化。
protected void prepareRefresh() {
    // Switch to active.
    this.startupDate = System.currentTimeMillis();
    this.closed.set(false);
    // 1.设置容器的状态为激活
    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.
    // 2.初始化 Environment 的 propertySources 属性
    //样例<context:property-placeholder location="classpath*:/config/load.properties"/>
    initPropertySources();

    // Validate that all properties marked as required are resolvable:
    // see ConfigurablePropertyResolver#setRequiredProperties
    // 3.校验 Environment 的 requiredProperties 是否都存在
    // 请参考 ConfigurablePropertyResolver#setRequiredProperties
    getEnvironment().validateRequiredProperties();

    // 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...
    // 4.创建事件集合
    this.earlyApplicationEvents = new LinkedHashSet<>();
}

表示在真正做refresh操作之前需要准备做的事情:

  • 设置Spring容器的启动时间。
  • 开启活跃状态,撤销关闭状态。
  • 初始化context environment(上下文环境)中的占位符属性来源。
  • 验证环境信息里一些必须存在的属性。

ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory()

对于XML容器(如FileSystemXmlApplicationContext)来说,这一步是非常重要的,主要为创建内部容器,该容器负责 Bean 的创建与管理,此步会进行BeanDefinition的注册。
而对于注解容器来说该方法仅仅是调用了子类容器的refreshBeanFactory()刷新子类容器

让这个类(AbstractApplicationContext)的子类刷新内部bean工厂。

  • AbstractRefreshableApplicationContext容器:实际上就是重新创建一个bean工厂,并设置工厂的一些属性。
  • GenericApplicationContext容器:获取创建容器的时候创建的bean工厂,并且设置工厂的ID。
/**
 * 通知此上下文的子类去加载或刷新其内在的bean工厂
 * Tell the subclass to refresh the internal bean factory.
 * @return the fresh BeanFactory instance 新的bean工厂实例
 * @see #refreshBeanFactory()
 * @see #getBeanFactory()
 */
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
    //调用子类容器的refreshBeanFactory()刷新子类容器
    refreshBeanFactory();
    return getBeanFactory();
}

public class GenericApplicationContext extends AbstractApplicationContext implements BeanDefinitionRegistry {

    private final DefaultListableBeanFactory beanFactory;

    @Override
    protected final void refreshBeanFactory() throws IllegalStateException {
        if (!this.refreshed.compareAndSet(false, true)) {
            throw new IllegalStateException(
                    "GenericApplicationContext does not support multiple refresh attempts: just call 'refresh' once");
        }
        this.beanFactory.setSerializationId(getId());
    }
}

prepareBeanFactory(beanFactory)

该方法主要是注册一些容器中需要的系统Bean,例如classloader,beanfactoryPostProcessor等

/**
 * Configure the factory's standard context characteristics,
 * such as the context's ClassLoader and post-processors.
 * 为BeanFactory设置各种功能,
 * 例如容器的ClassLoader类加载器和post-processors后置处理器。
 * @param beanFactory the BeanFactory to configure 要配置的bean工厂
 */
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
    // Tell the internal bean factory to use the context's class loader etc.
    // 告诉内部bean工厂使用容器的类加载器
    beanFactory.setBeanClassLoader(getClassLoader());
    // 设置beanFactory的表达式语言处理器,Spring3开始增加了对语言表达式的支持,默认可以使用#{bean.xxx}的形式来调用相关属性值
    beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
    // 为beanFactory增加一个默认的propertyEditor
    beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));

    // Configure the bean factory with context callbacks.
    //添加该处理器的作用:当应用程序定义的Bean实现ApplicationContextAware接口时注入ApplicationContext对象
    beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
    // 如果某个 bean 依赖于以下几个接口的实现类,在自动装配的时候忽略它们,
    // Spring 会通过其他方式来处理这些依赖。
    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 class接口的实现类,则在运行时修指定为当前BeanFactory
    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作为应用程序监听器
    //ApplicationListenerDetector的作用就是判断某个Bean是否是ApplicationListener,
    // 如果是,加入到事件监听者队列。
    beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));

    // Detect a LoadTimeWeaver and prepare for weaving, if found.
    // 如果找到一个LoadTimeWeaver,那么就准备将后置处理器“织入”bean工厂
    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.
    // 注册默认environment环境bean
    if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
        //环境信息ConfigurableEnvironment
        beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
    }
    if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
        //系统属性,systemProperties【Map<String, Object>】
        beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
    }
    if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
        //系统环境变量systemEnvironment【Map<String, Object>】
        beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
    }
}

postProcessBeanFactory(beanFactory)

允许容器的子类去注册postProcessor,钩子方法。此方法的实现在AbstractRefreshableWebApplicationContext类中,它是XmlWebApplicationContext的父类。进入方法查看:

/**
 * Register request/session scopes, a {@link ServletContextAwareProcessor}, etc.
 * 注册request/session scopes,一个ServletContextAwareProcessor处理器等。
 */
@Override
protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
    //ServletContextAwareProcessor中拿到应用上下文持有的servletContext引用和servletConfig引用
    //1.添加ServletContextAwareProcessor处理器
    beanFactory.addBeanPostProcessor(new ServletContextAwareProcessor(this.servletContext, this.servletConfig));

    //在自动注入时忽略指定的依赖接口
    //通常被应用上下文用来注册以其他方式解析的依赖项
    beanFactory.ignoreDependencyInterface(ServletContextAware.class);
    beanFactory.ignoreDependencyInterface(ServletConfigAware.class);
    
    //2.注册web应用的scopes
    WebApplicationContextUtils.registerWebApplicationScopes(beanFactory, this.servletContext);
    //3.注册和环境有关的beans
    WebApplicationContextUtils.registerEnvironmentBeans(beanFactory, this.servletContext, this.servletConfig);
}

上面对bean工厂进行了许多配置,现在需要对bean工厂进行一些处理。不同的Spring容器做不同的操作。比如GenericWebApplicationContext容器的操作会在BeanFactory中添加ServletContextAwareProcessor用于处理ServletContextAware类型的bean初始化的时候调用setServletContext或者setServletConfig方法(跟ApplicationContextAwareProcessor原理一样)。

GenericWebApplicationContext#postProcessBeanFactory源码:

/**
 * Register ServletContextAwareProcessor.
 * @see ServletContextAwareProcessor
 */
@Override
protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
    if (this.servletContext != null) {
        beanFactory.addBeanPostProcessor(new ServletContextAwareProcessor(this.servletContext));
        beanFactory.ignoreDependencyInterface(ServletContextAware.class);
    }
    WebApplicationContextUtils.registerWebApplicationScopes(beanFactory, this.servletContext);
    WebApplicationContextUtils.registerEnvironmentBeans(beanFactory, this.servletContext);
}

invokeBeanFactoryPostProcessors(beanFactory)

此方法激活在容器中注册为bean的BeanFactoryPostProcessors
对于注解容器来说,org.springframework.context.annotation.ConfigurationClassPostProcessor#postProcessBeanDefinitionRegistry方法扫描应用中所有BeanDefinition并注册到容器之中。

先介绍两个接口:

  • BeanFactoryPostProcessor:用来修改Spring容器中已经存在的bean的定义,使用ConfigurableListableBeanFactory对bean进行处理。
  • BeanDefinitionRegistryPostProcessor:继承BeanFactoryPostProcessor,作用跟BeanFactoryPostProcessor一样,只不过是使用BeanDefinitionRegistry对bean进行处理。

在Spring容器中找出实现了BeanFactoryPostProcessor接口的processor并执行。Spring容器会委托给PostProcessorRegistrationDelegate的invokeBeanFactoryPostProcessors方法执行。

注:
  • 1、在springboot的web程序初始化AnnotationConfigServletWebServerApplicationContext容器时,会初始化内部属性AnnotatedBeanDefinitionReader reader,这个reader构造的时候会在BeanFactory中注册一些post processor,包括BeanPostProcessor和BeanFactoryPostProcessor(比如ConfigurationClassPostProcessor、AutowiredAnnotationBeanPostProcessor):
AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
  • 2、在使用mybatis时,一般配置了MapperScannerConfigurer的bean,这个bean就是继承的BeanDefinitionRegistryPostProcessor,所以也是这个地方把扫描的mybatis的接口注册到容器中的。

invokeBeanFactoryPostProcessors方法处理BeanFactoryPostProcessor的逻辑如下:

从Spring容器中找出BeanDefinitionRegistryPostProcessor类型的bean(这些processor是在容器刚创建的时候通过构造AnnotatedBeanDefinitionReader的时候注册到容器中的),然后按照优先级分别执行,优先级的逻辑如下:

  • 实现PriorityOrdered接口的BeanDefinitionRegistryPostProcessor先全部找出来,然后排序后依次执行
  • 实现Ordered接口的BeanDefinitionRegistryPostProcessor找出来,然后排序后依次执行
    没有实现PriorityOrdered和Ordered接口的BeanDefinitionRegistryPostProcessor找出来执行并依次执行

接下来从Spring容器内查找BeanFactoryPostProcessor接口的实现类,然后执行(如果processor已经执行过,则忽略),这里的查找规则跟上面查找BeanDefinitionRegistryPostProcessor一样,先找PriorityOrdered,然后是Ordered,最后是两者都没。

这里需要说明的是ConfigurationClassPostProcessor这个processor是优先级最高的被执行的processor(实现了PriorityOrdered接口)。这个ConfigurationClassPostProcessor会去BeanFactory中找出所有有@Configuration注解的bean,然后使用ConfigurationClassParser去解析这个类。ConfigurationClassParser内部有个Map<ConfigurationClass, ConfigurationClass>类型的configurationClasses属性用于保存解析的类,ConfigurationClass是一个对要解析的配置类的封装,内部存储了配置类的注解信息、被@Bean注解修饰的方法、@ImportResource注解修饰的信息、ImportBeanDefinitionRegistrar等都存储在这个封装类中。

这里ConfigurationClassPostProcessor最先被处理还有另外一个原因是如果程序中有自定义的BeanFactoryPostProcessor,那么这个PostProcessor首先得通过ConfigurationClassPostProcessor被解析出来,然后才能被Spring容器找到并执行。(ConfigurationClassPostProcessor不先执行的话,这个Processor是不会被解析的,不会被解析的话也就不会执行了)。

  • 1、处理@PropertySources注解:进行一些配置信息的解析。

  • 2、处理@ComponentScan注解:使用ComponentScanAnnotationParser扫描basePackage下的需要解析的类(@SpringBootApplication注解也包括了@ComponentScan注解,只不过basePackages是空的,空的话会去获取当前@Configuration修饰的类所在的包),并注册到BeanFactory中(这个时候bean并没有进行实例化,而是进行了注册。具体的实例化在finishBeanFactoryInitialization方法中执行)。对于扫描出来的类,递归解析。

  • 3、处理@Import注解:先递归找出所有的注解,然后再过滤出只有@Import注解的类,得到@Import注解的值。
    比如查找@SpringBootApplication注解的@Import注解数据的话,首先发现@SpringBootApplication不是一个@Import注解,然后递归调用修饰了@SpringBootApplication的注解,发现有个@EnableAutoConfiguration注解,再次递归发现被@Import(EnableAutoConfigurationImportSelector.class)修饰,还有@AutoConfigurationPackage注解修饰,再次递归@AutoConfigurationPackage注解,发现被@Import(AutoConfigurationPackages.Registrar.class)注解修饰,所以@SpringBootApplication注解对应的@Import注解有2个,分别是@Import(AutoConfigurationPackages.Registrar.class)和@Import(EnableAutoConfigurationImportSelector.class)。找出所有的@Import注解之后,开始处理逻辑:

    • A、遍历这些@Import注解内部的属性类集合。
    • B、如果这个类是个ImportSelector接口的实现类,实例化这个ImportSelector,如果这个类也是DeferredImportSelector接口的实现类,那么加入ConfigurationClassParser的deferredImportSelectors属性中让第6步处理。否则调用ImportSelector的selectImports方法得到需要Import的类,然后对这些类递归做@Import注解的处理。
    • C、如果这个类是ImportBeanDefinitionRegistrar接口的实现类,设置到配置类的importBeanDefinitionRegistrars属性中。
    • D、其它情况下把这个类入队到ConfigurationClassParser的importStack(队列)属性中,然后把这个类当成是@Configuration注解修饰的类递归重头开始解析这个类。
  • 5、处理@ImportResource注解:获取@ImportResource注解的locations属性,得到资源文件的地址信息。然后遍历这些资源文件并把它们添加到配置类的importedResources属性中。

  • 6、处理@Bean注解:获取被@Bean注解修饰的方法,然后添加到配置类的beanMethods属性中。

  • 7、处理DeferredImportSelector:处理第3步@Import注解产生的DeferredImportSelector,进行selectImports方法的调用找出需要import的类,然后再调用第3步相同的处理逻辑处理。

这里@SpringBootApplication注解被@EnableAutoConfiguration修饰,@EnableAutoConfiguration注解被@Import(EnableAutoConfigurationImportSelector.class)修饰,所以在第3步会找出这个@Import修饰的类EnableAutoConfigurationImportSelector,这个类刚好实现了DeferredImportSelector接口,接着就会在第6步被执行。第6步selectImport得到的类就是自动化配置类。

EnableAutoConfigurationImportSelector的selectImport方法会在spring-boot-autoconfigure包的META-INF里面的spring.factories文件中找出key为org.springframework.boot.autoconfigure.EnableAutoConfiguration对应的值,有109个,这109个就是所谓的自动化配置类(XXXAutoConfiguration)。(如果引入了mybatis和pagehelper,也会在对应的XXXautoconfigure包的META-INF里面的spring.factories找到EnableAutoConfiguration,这样可能最后得到的自动配置类会大于109个。)然后在过滤排除一下不需要的配置,最后返回实际用到的。

ConfigurationClassParser解析完成之后,被解析出来的类会放到configurationClasses属性中。然后使用ConfigurationClassBeanDefinitionReader去解析这些类。

这个时候这些bean只是被加载到了Spring容器中。下面这段代码是ConfigurationClassBeanDefinitionReader的解析bean过程:这个时候这些bean只是被加载到了Spring容器中。下面这段代码是ConfigurationClassBeanDefinitionReader#loadBeanDefinitions的解析bean过程:

public void loadBeanDefinitions(Set<ConfigurationClass> configurationModel) {
    TrackedConditionEvaluator trackedConditionEvaluator = new TrackedConditionEvaluator();
    for (ConfigurationClass configClass : configurationModel) {
        //对每一个配置类,调用loadBeanDefinitionsForConfigurationClass方法
        loadBeanDefinitionsForConfigurationClass(configClass, trackedConditionEvaluator);
    }
}


private void loadBeanDefinitionsForConfigurationClass(
        ConfigurationClass configClass, TrackedConditionEvaluator trackedConditionEvaluator) {
    //使用条件注解判断是否需要跳过这个配置类
    if (trackedConditionEvaluator.shouldSkip(configClass)) {
        //跳过配置类的话在Spring容器中移除bean的注册
        String beanName = configClass.getBeanName();
        if (StringUtils.hasLength(beanName) && this.registry.containsBeanDefinition(beanName)) {
            this.registry.removeBeanDefinition(beanName);
        }
        this.importRegistry.removeImportingClass(configClass.getMetadata().getClassName());
        return;
    }

    if (configClass.isImported()) {
        //如果自身是被@Import注释所import的,注册自己
        registerBeanDefinitionForImportedConfigurationClass(configClass);
    }
    //注册方法中被@Bean注解修饰的bean
    for (BeanMethod beanMethod : configClass.getBeanMethods()) {
        loadBeanDefinitionsForBeanMethod(beanMethod);
    }
    //注册@ImportResource注解注释的资源文件中的bean
    loadBeanDefinitionsFromImportedResources(configClass.getImportedResources());
    //注册@Import注解中的ImportBeanDefinitionRegistrar接口的registerBeanDefinitions
    loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars());
}

invokeBeanFactoryPostProcessors方法总结来说就是从Spring容器中找出BeanDefinitionRegistryPostProcessor和BeanFactoryPostProcessor接口的实现类并按照一定的规则顺序进行执行。 其中ConfigurationClassPostProcessor这个BeanDefinitionRegistryPostProcessor优先级最高,它会对项目中的@Configuration注解修饰的类(@Component、@ComponentScan、@Import、@ImportResource修饰的类也会被处理)进行解析,解析完成之后把这些bean注册到BeanFactory中。需要注意的是这个时候注册进来的bean还没有实例化。

下面这图就是对ConfigurationClassPostProcessor后置器的总结:


registerBeanPostProcessors(beanFactory)

从Spring容器中找出的BeanPostProcessor接口的bean,并设置到BeanFactory的属性中。之后bean被实例化的时候会调用这个BeanPostProcessor。

该方法委托给了PostProcessorRegistrationDelegate类的registerBeanPostProcessors方法执行。这里的过程跟invokeBeanFactoryPostProcessors类似:

  • 1、先找出实现了PriorityOrdered接口的BeanPostProcessor并排序后加到BeanFactory的BeanPostProcessor集合中。

  • 2、找出实现了Ordered接口的BeanPostProcessor并排序后加到BeanFactory的BeanPostProcessor集合中。

  • 3、没有实现PriorityOrdered和Ordered接口的BeanPostProcessor加到BeanFactory的BeanPostProcessor集合中。

这些已经存在的BeanPostProcessor在postProcessBeanFactory方法中已经说明,都是由AnnotationConfigUtils的registerAnnotationConfigProcessors方法注册的。这些BeanPostProcessor包括有AutowiredAnnotationBeanPostProcessor(处理被@Autowired注解修饰的bean并注入)、RequiredAnnotationBeanPostProcessor(处理被@Required注解修饰的方法)、CommonAnnotationBeanPostProcessor(处理@PreDestroy、@PostConstruct、@Resource等多个注解的作用)等。

如果是自定义的BeanPostProcessor,已经被ConfigurationClassPostProcessor注册到容器内。

这些BeanPostProcessor会在这个方法内被实例化(通过调用BeanFactory的getBean方法,如果没有找到实例化的类,就会去实例化)。

initMessageSource()

初始化MessageSource组件(做国际化功能;消息绑定,消息解析),这个接口提供了消息处理功能。主要用于国际化/i18n。

initApplicationEventMulticaster()

在Spring容器中初始化事件广播器,事件广播器用于事件的发布。

程序首先会检查bean工厂中是否有bean的名字和这个常量(applicationEventMulticaster)相同的,如果没有则就使用默认的ApplicationEventMulticaster 的实现:SimpleApplicationEventMulticaster。

/**
 * Initialize the ApplicationEventMulticaster.
 * Uses SimpleApplicationEventMulticaster if none defined in the context.
 * 初始化ApplicationEventMulticaster。
 * 如果在上下文中没有定义,则使用SimpleApplicationEventMulticaster。
 * @see org.springframework.context.event.SimpleApplicationEventMulticaster
 */
protected void initApplicationEventMulticaster() {
    ConfigurableListableBeanFactory beanFactory = getBeanFactory();
    // 如果容器存在ApplicationEventMulticaster的bean实例,则赋值给容器的applicationEventMulticaster
    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 {
        // 没有则新建 SimpleApplicationEventMulticaster,
        // 并完成 SimpleApplicationEventMulticaster Bean 的注册
        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()

一个模板方法,不同的Spring容器做不同的事情。
预留给 AbstractApplicationContext 的子类用于初始化其他特殊的 bean,该方法需要在所有单例 bean 初始化之前调用:

  • 比如,Spring的化Web容器就会去初始化一些和主题展示相关的Bean(ThemeSource)
public abstract class AbstractRefreshableWebApplicationContext extends AbstractRefreshableConfigApplicationContext
        implements ConfigurableWebApplicationContext, ThemeSource {

    @Override
    protected void onRefresh() {
        this.themeSource = UiApplicationContextUtils.initThemeSource(this);
    }
}
  • 而SpringBoot,web程序的容器ServletWebServerApplicationContext中会调用createWebServer方法去创建内置的Servlet容器。

目前SpringBoot只支持3种内置的Servlet容器:

  • Tomcat
  • Jetty
  • Undertow

registerListeners()

注册应用的监听器。就是注册实现了ApplicationListener接口的监听器bean,这些监听器是注册到ApplicationEventMulticaster中的。这不会影响到其它监听器bean。在注册完以后,还会将其前期的事件发布给相匹配的监听器。

/**
 * Add beans that implement ApplicationListener as listeners.
 * Doesn't affect other listeners, which can be added without being beans.
 * 添加应用程序监听器作为监听器的bean。
 * 不影响其他监听器,可以在没有bean的情况下添加。
 */
protected void registerListeners() {
    // Register statically specified listeners first.
    //从容器中拿到所有已经创建的ApplicationListener
    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!
    // 不要在这里初始化factorybean:我们需要保留所有未初始化的常规bean(事件监听器),
    // 让后处理器应用到它们!
    // 获取所有还没有创建的ApplicationListener
    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...
    // 至此,已经完成将监听器注册到ApplicationEventMulticaster中,
    // 现在我们最终拥有一个多路广播器来发布前期的应用程序事件给监听器.
    Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
    this.earlyApplicationEvents = null;
    if (earlyEventsToProcess != null) {
        for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
            //派发之前步骤产生的事件
            getApplicationEventMulticaster().multicastEvent(earlyEvent);
        }
    }
}

finishBeanFactoryInitialization(beanFactory)

实例化BeanFactory中已经被注册但是未实例化的所有实例(懒加载的不需要实例化)。
比如invokeBeanFactoryPostProcessors方法中根据各种注解解析出来的类,在这个时候都会被初始化。
实例化的过程各种BeanPostProcessor开始起作用。

该方法会实例化所有剩余的非懒加载单例 bean。除了一些内部的 bean、实现了 BeanFactoryPostProcessor 接口的 bean、实现了 BeanPostProcessor 接口的 bean,其他的非懒加载单例 bean 都会在这个方法中被实例化,并且 BeanPostProcessor 的触发也是在这个方法中。

/**
 * Finish the initialization of this context's bean factory,
 * initializing all remaining singleton beans.
 * 完成此上下文的bean工厂的初始化,初始化所有剩余的单例bean
 */
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
    // Initialize conversion service for this context.
    // 初始化此容器的转换器
    // 转换器的职责是处理通过配置给Bean实例成员变量赋值的时候的类型转换工作
    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.
    // 如果没有注册过bean后置处理器post-processor,则注册默认的解析器
    // (例如主要用于解析properties文件的PropertyPlaceholderConfigurer )
    // @value注解或在xml中使用${}的方式进行环境相关的配置
    if (!beanFactory.hasEmbeddedValueResolver()) {
        beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));
    }

    // Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early.
    // AOP分为三种方式:编译期织入、类加载期织入和运行期织入
    // LoadTimeWeaving属于第二种,主要通过JVM进行织入
    // 先初始化LoadTimeWeaverAware bean,以便尽早注册它们的transformers
    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.
    // 允许缓存所有bean定义元数据,不希望有进一步的更改
    beanFactory.freezeConfiguration();

    // Instantiate all remaining (non-lazy-init) singletons.
    // 实例化所有剩余的(non-lazy-init非延时加载的)单例
    beanFactory.preInstantiateSingletons();
}

实例化所有剩余(非懒加载)单例对象。

MergedBeanDefinition

在之后的内容你可能会频繁的见到 “MergedBeanDefinition” 这个词,因此这边先稍微讲解一下,有助于你更好的理解。

MergedBeanDefinition:这个词其实不是一个官方词,但是很接近,该词主要是用来表示 “合并的 bean 定义”,因为每次都写 “合并的 bean 定义” 有点太绕口,因此我在之后的注释或解析中或统一使用 MergedBeanDefinition 来表示 “合并的 bean 定义”。

之所以称之为 “合并的”,是因为存在 “子定义” 和 “父定义” 的情况。对于一个 bean 定义来说,可能存在以下几种情况:

  • 该 BeanDefinition 存在 “父定义”:首先使用 “父定义” 的参数构建一个 RootBeanDefinition,然后再使用该 BeanDefinition 的参数来进行覆盖。

  • 该 BeanDefinition 不存在 “父定义”,并且该 BeanDefinition 的类型是 RootBeanDefinition:直接返回该 RootBeanDefinition 的一个克隆。

  • 该 BeanDefinition 不存在 “父定义”,但是该 BeanDefinition 的类型不是 RootBeanDefinition:使用该 BeanDefinition 的参数构建一个 RootBeanDefinition。

通常 BeanDefinition 在之前加载到 BeanFactory 中的时候,通常是被封装成 GenericBeanDefinition 或 ScannedGenericBeanDefinition,但是从这边之后 bean 的后续流程处理都是针对 RootBeanDefinition,因此在这边会统一将 BeanDefinition 转换成 RootBeanDefinition。

在我们日常使用的过程中,如果我们使用 XML 配置来注册 bean,则该 bean 定义会被封装成:GenericBeanDefinition;如果我们使用注解的方式来注册 bean,也就是<context:component-scan /> + @Compoment,则该 bean 定义会被封装成 ScannedGenericBeanDefinition。

beanFactory.preInstantiateSingletons()

实例化所有剩余的(non-lazy-init非延时加载的)单例

public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory
        implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable {

    @Override
    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.
        // 1.创建beanDefinitionNames的副本beanNames用于后续的遍历,以允许init等方法注册新的bean定义
        List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);

        // Trigger initialization of all non-lazy singleton beans...
        // 2.遍历beanNames,触发所有非懒加载单例bean的初始化
        for (String beanName : beanNames) {
            // 3.获取beanName对应的MergedBeanDefinition
            RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
            // 4.bd对应的Bean实例:不是抽象类 && 是单例 && 不是懒加载
            if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
                // 5.判断beanName对应的bean是否为FactoryBean
                if (isFactoryBean(beanName)) {
                    // 5.1 通过beanName获取FactoryBean实例
                    // 通过getBean(&beanName)拿到的是FactoryBean本身;通过getBean(beanName)拿到的是FactoryBean创建的Bean实例
                    Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
                    if (bean instanceof FactoryBean) {
                        final FactoryBean<?> factory = (FactoryBean<?>) bean;
                        // 5.2 判断这个FactoryBean是否希望急切的初始化
                        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());
                        }
                        // 5.3 如果希望急切的初始化,则通过beanName获取bean实例
                        if (isEagerInit) {
                            getBean(beanName);
                        }
                    }
                }
                else {
                    // 6.如果beanName对应的bean不是FactoryBean,只是普通Bean,通过beanName获取bean实例
                    getBean(beanName);
                }
            }
        }

        // Trigger post-initialization callback for all applicable beans...
        // 7.遍历beanNames,触发所有SmartInitializingSingleton的后初始化回调
        for (String beanName : beanNames) {
            // 7.1 拿到beanName对应的bean实例
            Object singletonInstance = getSingleton(beanName);
            // 7.2 判断singletonInstance是否实现了SmartInitializingSingleton接口
            if (singletonInstance instanceof SmartInitializingSingleton) {
                final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
                // 7.3 触发SmartInitializingSingleton实现类的afterSingletonsInstantiated方法
                if (System.getSecurityManager() != null) {
                    AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
                        smartSingleton.afterSingletonsInstantiated();
                        return null;
                    }, getAccessControlContext());
                }
                else {
                    smartSingleton.afterSingletonsInstantiated();
                }
            }
        }
    }
}
  • 获取 beanName 对应的 MergedBeanDefinition。
  • 判断 beanName 对应的 bean 是否为 FactoryBean。
  • 通过 beanName 获取 bean 实例,finishBeanFactoryInitialization 方法的核心,限于篇幅,在下一篇文章开始介绍。
  • 遍历 beanNames,触发所有 SmartInitializingSingleton 的后初始化回调,这是 Spring 提供的一个扩展点,在所有非懒加载单例实例化结束后调用。

RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName)

public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport implements ConfigurableBeanFactory {

    protected RootBeanDefinition getMergedLocalBeanDefinition(String beanName) throws BeansException {
        // Quick check on the concurrent map first, with minimal locking.
        // 1.检查beanName对应的MergedBeanDefinition是否存在于缓存中
        RootBeanDefinition mbd = this.mergedBeanDefinitions.get(beanName);
        if (mbd != null && !mbd.stale) {
            // 2.如果存在于缓存中则直接返回
            return mbd;
        }
        // 3.如果不存在于缓存中
        // 3.1 getBeanDefinition(beanName): 获取beanName对应的BeanDefinition,从beanDefinitionMap缓存中获取
        // 3.2 getMergedBeanDefinition: 根据beanName和对应的BeanDefinition,获取MergedBeanDefinition
        return getMergedBeanDefinition(beanName, getBeanDefinition(beanName));
    }
}

根据 beanName 和 beanName 对应的 BeanDefinition,获取 MergedBeanDefinition

getMergedBeanDefinition(beanName, getBeanDefinition(beanName))

public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport implements ConfigurableBeanFactory {

    protected RootBeanDefinition getMergedBeanDefinition(String beanName, BeanDefinition bd)
            throws BeanDefinitionStoreException {

        return getMergedBeanDefinition(beanName, bd, null);
    }

    protected RootBeanDefinition getMergedBeanDefinition(
            String beanName, BeanDefinition bd, @Nullable BeanDefinition containingBd)
            throws BeanDefinitionStoreException {
        // 1.加锁再进行操作
        synchronized (this.mergedBeanDefinitions) {
            // 用于存储bd的MergedBeanDefinition,也就是该方法的结果
            RootBeanDefinition mbd = null;
            RootBeanDefinition previous = null;

            // Check with full lock now in order to enforce the same merged instance.
            if (containingBd == null) {
                // 2.检查beanName对应的MergedBeanDefinition是否存在于缓存中
                mbd = this.mergedBeanDefinitions.get(beanName);
            }
            // 3.如果beanName对应的MergedBeanDefinition不存在于缓存中
            if (mbd == null || mbd.stale) {
                previous = mbd;
                if (bd.getParentName() == null) {
                    // 4.如果bd的parentName为空,代表bd没有父定义,无需与父定义进行合并操作,
                    // 也就是bd的MergedBeanDefinition就是bd本身(可能需要转成RootBeanDefinition)
                    // Use copy of given root bean definition.
                    if (bd instanceof RootBeanDefinition) {
                        // 4.1 如果bd的类型为RootBeanDefinition,则bd的MergedBeanDefinition就是bd本身,则直接克隆一个副本
                        mbd = ((RootBeanDefinition) bd).cloneBeanDefinition();
                    }
                    else {
                        // 4.2 否则,将bd作为参数,构建一个RootBeanDefinition。
                        // 正常使用下,BeanDefinition在被加载后是GenericBeanDefinition或ScannedGenericBeanDefinition
                        mbd = new RootBeanDefinition(bd);
                    }
                }
                else {
                    // 5.否则,bd存在父定义,需要与父定义合并
                    // Child bean definition: needs to be merged with parent.
                    BeanDefinition pbd;
                    try {
                        // 5.1 获取父定义的beanName
                        String parentBeanName = transformedBeanName(bd.getParentName());
                        // 5.2 如果父定义的beanName与该bean的beanName不同
                        if (!beanName.equals(parentBeanName)) {
                            // 5.3 获取父定义的MergedBeanDefinition(因为父定义也可能有父定义,也就是bd的爷爷定义...)
                            pbd = getMergedBeanDefinition(parentBeanName);
                        }
                        else {
                            // 5.4 如果父定义的beanName与bd的beanName相同,则拿到父BeanFactory,
                            // 只有在存在父BeanFactory的情况下,才允许父定义beanName与自己相同,否则就是将自己设置为父定义
                            BeanFactory parent = getParentBeanFactory();
                            if (parent instanceof ConfigurableBeanFactory) {
                                // 5.5 如果父BeanFactory是ConfigurableBeanFactory,则通过父BeanFactory获取父定义的MergedBeanDefinition
                                pbd = ((ConfigurableBeanFactory) parent).getMergedBeanDefinition(parentBeanName);
                            }
                            else {
                                // 5.6 如果父BeanFactory不是ConfigurableBeanFactory,则抛异常
                                throw new NoSuchBeanDefinitionException(parentBeanName,
                                        "Parent name '" + parentBeanName + "' is equal to bean name '" + beanName +
                                        "': cannot be resolved without a ConfigurableBeanFactory parent");
                            }
                        }
                    }
                    catch (NoSuchBeanDefinitionException ex) {
                        throw new BeanDefinitionStoreException(bd.getResourceDescription(), beanName,
                                "Could not resolve parent bean definition '" + bd.getParentName() + "'", ex);
                    }
                    // Deep copy with overridden values.
                    // 5.7 使用父定义pbd构建一个新的RootBeanDefinition对象(深拷贝)
                    mbd = new RootBeanDefinition(pbd);
                    // 5.8 使用bd覆盖父定义
                    mbd.overrideFrom(bd);
                }

                // Set default singleton scope, if not configured before.
                // 6.如果没有配置scope,则设置成默认的singleton
                if (!StringUtils.hasLength(mbd.getScope())) {
                    mbd.setScope(SCOPE_SINGLETON);
                }

                // A bean contained in a non-singleton bean cannot be a singleton itself.
                // Let's correct this on the fly here, since this might be the result of
                // parent-child merging for the outer bean, in which case the original inner bean
                // definition will not have inherited the merged outer bean's singleton status.
                // 7.如果containingBd不为空 && containingBd不为singleton && mbd为singleton,则将mdb的scope设置为containingBd的scope
                if (containingBd != null && !containingBd.isSingleton() && mbd.isSingleton()) {
                    mbd.setScope(containingBd.getScope());
                }

                // Cache the merged bean definition for the time being
                // (it might still get re-merged later on in order to pick up metadata changes)
                // 8.将beanName与mbd放到mergedBeanDefinitions缓存,以便之后可以直接使用
                if (containingBd == null && isCacheBeanMetadata()) {
                    this.mergedBeanDefinitions.put(beanName, mbd);
                }
            }
            if (previous != null) {
                copyRelevantMergedBeanDefinitionCaches(previous, mbd);
            }
            // 9.返回MergedBeanDefinition
            return mbd;
        }
    }
}
  • 获取父定义的 beanName,这边有一个 beanName 的转换操作,之后会经常用到。

  • String parentBeanName = transformedBeanName(bd.getParentName())获取父定义的 MergedBeanDefinition

  • mbd = new RootBeanDefinition(pbd)和mbd.overrideFrom(bd);合并操作,也就是我们之前一直说的 MergedBeanDefinition 的由来。

  • 将该 beanName 与 MergedBeanDefinition 放到 mergedBeanDefinitions 缓存,后续再走到getMergedLocalBeanDefinition时,就会直接返回缓存里的数据。

String parentBeanName = transformedBeanName(bd.getParentName())

public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport implements ConfigurableBeanFactory {

    protected String transformedBeanName(String name) {
        return canonicalName(BeanFactoryUtils.transformedBeanName(name));
    }

}

public abstract class BeanFactoryUtils {
    public static String transformedBeanName(String name) {
        Assert.notNull(name, "'name' must not be null");
        if (!name.startsWith(BeanFactory.FACTORY_BEAN_PREFIX)) {
            return name;
        }
        return transformedBeanNameCache.computeIfAbsent(name, beanName -> {
            do {
                // 如果beanName带有 "&" 前缀,则去掉
                beanName = beanName.substring(BeanFactory.FACTORY_BEAN_PREFIX.length());
            }
            while (beanName.startsWith(BeanFactory.FACTORY_BEAN_PREFIX));
            return beanName;
        });
    }
}

public class SimpleAliasRegistry implements AliasRegistry {

    /**
     * 根据给定的别名获取规范名称
     * Determine the raw name, resolving aliases to canonical names.
     * @param name the user-specified name
     * @return the transformed name
     */
    public String canonicalName(String name) {
        String canonicalName = name;
        // Handle aliasing...
        String resolvedName;
        do {
            // 将别名解析成真正的beanName
            //获取给定别名的规范名称,获取到跳出循环
            resolvedName = this.aliasMap.get(canonicalName);
            if (resolvedName != null) {
                canonicalName = resolvedName;
            }
        }
        while (resolvedName != null);
        return canonicalName;
    }
}

将 name 真正解析成真正的 beanName,主要是去掉 FactoryBean 里的 “&” 前缀,和解析别名。这边简单的介绍下 FactoryBean。

要理解FactoryBean和Bean的区别
一般情况下,Spring 通过反射机制利用 bean 的 class 属性指定实现类来实例化 bean。而 FactoryBean 是一种特殊的 bean,它是个工厂 bean,可以自己创建 bean 实例,如果一个类实现了 FactoryBean 接口,则该类可以自己定义创建实例对象的方法,只需要实现它的 getObject() 方法。

注:很多中间件都利用 FactoryBean 来进行扩展。

引入了几个重要的缓存:

  • mergedBeanDefinitions 缓存:beanName -> 合并的 bean 定义。
  • beanDefinitionMap 缓存:beanName -> BeanDefinition。
  • singletonObjects 缓存:beanName -> 单例 bean 对象。
  • earlySingletonObjects 缓存:beanName -> 单例 bean 对象,该缓存存放的是早期单例 bean 对象,可以理解成还未进行属性填充、初始化。
  • singletonFactories 缓存:beanName -> ObjectFactory。
  • singletonsCurrentlyInCreation 缓存:当前正在创建单例 bean 对象的 beanName 集合。

pbd = getMergedBeanDefinition(parentBeanName);

获取父定义的MergedBeanDefinition

public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport implements ConfigurableBeanFactory {

    @Override
    public BeanDefinition getMergedBeanDefinition(String name) throws BeansException {
        // 1.获取真正的beanName(解析别名)
        String beanName = transformedBeanName(name);
        // Efficiently check whether bean definition exists in this factory.
        if (!containsBeanDefinition(beanName) && getParentBeanFactory() instanceof ConfigurableBeanFactory) {
            // 2.如果当前BeanFactory中不存在beanName的Bean定义 && 父beanFactory是ConfigurableBeanFactory,
            // 则调用父BeanFactory去获取beanName的MergedBeanDefinition
            return ((ConfigurableBeanFactory) getParentBeanFactory()).getMergedBeanDefinition(beanName);
        }
        // Resolve merged bean definition locally.
        // 3.在当前BeanFactory中解析beanName的MergedBeanDefinition
        return getMergedLocalBeanDefinition(beanName);
    }
}
父 BeanFactory

在 Spring 中可能存在多个 BeanFactory,多个 BeanFactory 可能存在 “父工厂” 与 “子工厂” 的关系。最常见的例子就是:Spring MVC 的 BeanFactory 和 Spring 的 BeanFactory,通常情况下,Spring 的 BeanFactory 是 “父工厂”,Spring MVC 的 BeanFactory 是 “子工厂”,在 Spring 中,子工厂可以使用父工厂的 BeanDefinition,因而,如果在当前 BeanFactory 中找不到,而又存在父工厂,则会去父工厂中查找。

isFactoryBean(String name)

public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport implements ConfigurableBeanFactory {

    @Override
    public boolean isFactoryBean(String name) throws NoSuchBeanDefinitionException {
        // 1.拿到真正的beanName(去掉&前缀、解析别名)
        String beanName = transformedBeanName(name);
        // 2.尝试从缓存获取Bean实例对象
        Object beanInstance = getSingleton(beanName, false);
        if (beanInstance != null) {
            // 3.beanInstance存在,则直接判断类型是否为FactoryBean
            return (beanInstance instanceof FactoryBean);
        }
        // No singleton instance found -> check bean definition.
        if (!containsBeanDefinition(beanName) && getParentBeanFactory() instanceof ConfigurableBeanFactory) {
            // No bean definition found in this factory -> delegate to parent.
            // 5.如果缓存中不存在此beanName && 父beanFactory是ConfigurableBeanFactory,则调用父BeanFactory判断是否为FactoryBean
            return ((ConfigurableBeanFactory) getParentBeanFactory()).isFactoryBean(name);
        }
        // 6.通过MergedBeanDefinition来检查beanName对应的Bean是否为FactoryBean
        return isFactoryBean(beanName, getMergedLocalBeanDefinition(beanName));
    }
}
  • 尝试从缓存获取 bean 实例对象
  • 通过 MergedBeanDefinition 来检查 beanName 对应的 bean 是否为 FactoryBean。首先通过 getMergedLocalBeanDefinition 方法获取 beanName 的 MergedBeanDefinition,接着调用 isFactoryBean 来检查 beanName 对应的 bean 是否为 FactoryBean。

Object beanInstance = getSingleton(beanName, false)

public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {

    /** Cache of singleton objects: bean name to bean instance. */
    private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);

    /** Cache of singleton factories: bean name to ObjectFactory. */
    private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);

    /** Cache of early singleton objects: bean name to bean instance. */
    private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);
    
    protected Object getSingleton(String beanName, boolean allowEarlyReference) {
        // 1.从单例对象缓存中获取beanName对应的单例对象
        Object singletonObject = this.singletonObjects.get(beanName);
        // 2.如果单例对象缓存中没有,并且该beanName对应的单例bean正在创建中
        if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
            // 3.加锁进行操作
            synchronized (this.singletonObjects) {
                // 4.从早期单例对象缓存中获取单例对象(之所称成为早期单例对象,是因为earlySingletonObjects里
                // 的对象的都是通过提前曝光的ObjectFactory创建出来的,还未进行属性填充等操作)
                singletonObject = this.earlySingletonObjects.get(beanName);
                // 5.如果在早期单例对象缓存中也没有,并且允许创建早期单例对象引用
                if (singletonObject == null && allowEarlyReference) {
                    // 6.从单例工厂缓存中获取beanName的单例工厂
                    ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
                    if (singletonFactory != null) {
                        // 7.如果存在单例对象工厂,则通过工厂创建一个单例对象
                        singletonObject = singletonFactory.getObject();
                        // 8.将通过单例对象工厂创建的单例对象,放到早期单例对象缓存中
                        this.earlySingletonObjects.put(beanName, singletonObject);
                        // 9.移除该beanName对应的单例对象工厂,因为该单例工厂已经创建了一个实例对象,并且放到earlySingletonObjects缓存了,
                        // 因此,后续获取beanName的单例对象,可以通过earlySingletonObjects缓存拿到,不需要在用到该单例工厂
                        this.singletonFactories.remove(beanName);
                    }
                }
            }
        }
        // 10.返回单例对象
        return singletonObject;
    }

    public boolean isSingletonCurrentlyInCreation(String beanName) {
        return this.singletonsCurrentlyInCreation.contains(beanName);
    }
}

这段代码很重要,在正常情况下,该代码很普通,只是正常的检查下我们要拿的 bean 实例是否存在于缓存中,如果有就返回缓存中的 bean 实例,否则就返回 null。

这段代码之所以重要,是因为该段代码是 Spring 解决循环引用的核心代码。

解决循环引用逻辑:使用构造函数创建一个 “不完整” 的 bean 实例(之所以说不完整,是因为此时该 bean 实例还未初始化),并且提前曝光该 bean 实例的 ObjectFactory(提前曝光就是将 ObjectFactory 放到 singletonFactories 缓存),通过 ObjectFactory 我们可以拿到该 bean 实例的引用,如果出现循环引用,我们可以通过缓存中的 ObjectFactory 来拿到 bean 实例,从而避免出现循环引用导致的死循环。这边通过缓存中的 ObjectFactory 拿到的 bean 实例虽然拿到的是 “不完整” 的 bean 实例,但是由于是单例,所以后续初始化完成后,该 bean 实例的引用地址并不会变,所以最终我们看到的还是完整 bean 实例。

这段解决逻辑涉及到了后面的一些内容,所以可能会看的不是很理解,可以先有个印象,等把创建 bean 实例都看完了,再回过头来看,可能会好理解一点。

另外这个代码块中引进了4个重要缓存:

  • singletonObjects 缓存:beanName -> 单例 bean 对象。
  • earlySingletonObjects 缓存:beanName -> 单例 bean 对象,该缓存存放的是早期单例 bean 对象,可以理解成还未进行属性填充、初始化。
  • singletonFactories 缓存:beanName -> ObjectFactory。
  • singletonsCurrentlyInCreation 缓存:当前正在创建单例 bean 对象的 beanName 集合。

singletonObjects、earlySingletonObjects、singletonFactories 在这边构成了一个类似于 “三级缓存” 的概念。

isFactoryBean(beanName, getMergedLocalBeanDefinition(beanName))

通过MergedBeanDefinition来检查beanName对应的Bean是否为FactoryBean

public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport implements ConfigurableBeanFactory {

    protected boolean isFactoryBean(String beanName, RootBeanDefinition mbd) {
        Boolean result = mbd.isFactoryBean;
        if (result == null) {
            // 1.拿到beanName对应的Bean实例的类型
            Class<?> beanType = predictBeanType(beanName, mbd, FactoryBean.class);
            result = (beanType != null && FactoryBean.class.isAssignableFrom(beanType));
            mbd.isFactoryBean = result;
        }
        // 2.返回beanType是否为FactoryBean本身、子类或子接口
        return result;
    }
}

Class<?> beanType = predictBeanType(beanName, mbd, FactoryBean.class)

拿到beanName对应的Bean实例的类型

public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory
        implements AutowireCapableBeanFactory {

    protected Class<?> predictBeanType(String beanName, RootBeanDefinition mbd, Class<?>... typesToMatch) {
        // 1.拿到beanName的类型
        Class<?> targetType = determineTargetType(beanName, mbd, typesToMatch);
        // Apply SmartInstantiationAwareBeanPostProcessors to predict the
        // eventual type after a before-instantiation shortcut.
        // 2.应用SmartInstantiationAwareBeanPostProcessors后置处理器,来预测实例化的最终类型,
        // SmartInstantiationAwareBeanPostProcessors继承了InstantiationAwareBeanPostProcessor,
        // InstantiationAwareBeanPostProcessor的postProcessBeforeInstantiation方法可以改变Bean实例的类型,
        // 而SmartInstantiationAwareBeanPostProcessors的predictBeanType方法可以预测这个类型
        if (targetType != null && !mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
            boolean matchingOnlyFactoryBean = typesToMatch.length == 1 && typesToMatch[0] == FactoryBean.class;
            for (BeanPostProcessor bp : getBeanPostProcessors()) {
                if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
                    SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
                    // 3.调用predictBeanType方法
                    Class<?> predicted = ibp.predictBeanType(targetType, beanName);
                    if (predicted != null &&
                            (!matchingOnlyFactoryBean || FactoryBean.class.isAssignableFrom(predicted))) {
                        // 4.如果predicted不为空 && (typesToMatch长度不为1 || typesToMatch[0]不为FactoryBean.class ||
                        // predicted是FactoryBean本身、子类或子接口),则返回predicted
                        return predicted;
                    }
                }
            }
        }
        // 5.否则返回beanName的类型
        return targetType;
    }
}

这边走的是 AbstractAutowireCapableBeanFactory 里的方法,而不是 AbstractBeanFactory 里的方法。通过前面的介绍,我们知道创建的 BeanFactory 为 DefaultListableBeanFactory,而 DefaultListableBeanFactory 继承了 AbstractAutowireCapableBeanFactory,因此这边会走 AbstractAutowireCapableBeanFactory 的重写方法。

finishBeanFactoryInitialization()方法,执行了创建 bean 实例前的一些准备操作。主要是引入了 FactoryBean 这一特殊的 bean,获取 BeanDefinition 的 MergedBeanDefinition,最后将 BeanDefinition 统一转换成 RootBeanDefinition。

另外,finishBeanFactoryInitialization还引入了几个重要的缓存,如下:

  • mergedBeanDefinitions 缓存:beanName -> 合并的 bean 定义。
  • beanDefinitionMap 缓存:beanName -> BeanDefinition。
  • singletonObjects 缓存:beanName -> 单例 bean 对象。
  • earlySingletonObjects 缓存:beanName -> 单例 bean 对象,该缓存存放的是早期单例 bean 对象,可以理解成还未进行属性填充、初始化。
  • singletonFactories 缓存:beanName -> ObjectFactory。
  • singletonsCurrentlyInCreation 缓存:当前正在创建单例 bean 对象的 beanName 集合。

Spring 中大量使用了本地缓存,基本上通过名字和注释就能理解缓存的作用了。

finishRefresh()

refresh做完之后需要做的其他事情。

  • 初始化生命周期处理器,并设置到Spring容器中(LifecycleProcessor)
  • 调用生命周期处理器的onRefresh方法,这个方法会找出Spring容器中实现了SmartLifecycle接口的类并进行start方法的调用
  • 发布ContextRefreshedEvent事件告知对应的ApplicationListener进行响应的操作

如果是web容器ServletWebServerApplicationContext还会启动web服务和发布消息

/**
 * Finish the refresh of this context, invoking the LifecycleProcessor's
 * onRefresh() method and publishing the
 * 完成此上下文的刷新,调用LifecycleProcessor的onRefresh()方法
 * 并发布org.springframework.context.event.ContextRefreshedEvent 事件
 * {@link org.springframework.context.event.ContextRefreshedEvent}.
 */
protected void finishRefresh() {
    // Clear context-level resource caches (such as ASM metadata from scanning).
    // 清除上下文级别的资源缓存(如扫描的ASM元数据)
    clearResourceCaches();

    // Initialize lifecycle processor for this context.
    // 为这个上下文初始化生命周期处理器
    initLifecycleProcessor();

    // Propagate refresh to lifecycle processor first.
    // 首先将刷新传播到生命周期处理器
    getLifecycleProcessor().onRefresh();

    // Publish the final event.
    // 发布最终事件
    publishEvent(new ContextRefreshedEvent(this));

    // Participate in LiveBeansView MBean, if active.
    // 如果处于激活状态,将参与到 LiveBeansView MBean 中.
    LiveBeansView.registerApplicationContext(this);
}

参考:
https://www.cnblogs.com/grasp/p/11942735.html

https://www.cnblogs.com/feng-jq/p/10282260.html

https://www.cnblogs.com/toby-xu/p/11332666.html

https://zhuanlan.zhihu.com/p/83475033

https://www.cnblogs.com/grasp/p/11971887.html

https://www.cnblogs.com/grasp/p/11971887.html

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,271评论 5 466
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,725评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,252评论 0 328
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,634评论 1 270
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,549评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 47,985评论 1 275
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,471评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,128评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,257评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,233评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,235评论 1 328
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,940评论 3 316
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,528评论 3 302
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,623评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,858评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,245评论 2 344
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,790评论 2 339