spring-refresh方法执行步骤

本次源码分析基于版本springBoot2.3.7

1、查看SpringApplication的run方法

public ConfigurableApplicationContext run(String... args) {
    StopWatch stopWatch = new StopWatch();
    stopWatch.start();
    ConfigurableApplicationContext context = null;
    Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
    configureHeadlessProperty();
    SpringApplicationRunListeners listeners = getRunListeners(args);
    listeners.starting();
    try {
        ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
        ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);
        configureIgnoreBeanInfo(environment);
        Banner printedBanner = printBanner(environment);
        context = createApplicationContext();
        exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class,
                new Class[] { ConfigurableApplicationContext.class }, context);
        prepareContext(context, environment, listeners, applicationArguments, printedBanner);
        
        //此步骤为执行applicationContext上下文刷新
        refreshContext(context);

        afterRefresh(context, applicationArguments);
        stopWatch.stop();
        if (this.logStartupInfo) {
            new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);
        }
        listeners.started(context);
        callRunners(context, applicationArguments);
    }
    catch (Throwable ex) {
        handleRunFailure(context, ex, exceptionReporters, listeners);
        throw new IllegalStateException(ex);
    }

    try {
        listeners.running(context);
    }
    catch (Throwable ex) {
        handleRunFailure(context, ex, exceptionReporters, null);
        throw new IllegalStateException(ex);
    }
    return context;
}
View Code

2、查看SpringApplication的refreshContext方法,最终发现调用了AbstractApplicationContext的refresh()方法,refresh具体逻辑如下:

public void refresh() throws BeansException, IllegalStateException {
    synchronized (this.startupShutdownMonitor) {
        //1、准备此上下文以进行刷新,设置其启动日期和活动标志以及执行属性源的任何初始化。
        prepareRefresh();
        //2、告诉子类刷新内部bean工厂
        ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
        //3、准备bean工厂以便在此上下文中使用
        prepareBeanFactory(beanFactory);
        try {
            //4、允许在上下文子类中对bean工厂进行后置处理类,可以继续向BeanFactory中再添加一些东西
            postProcessBeanFactory(beanFactory);
            //5、实例化并调用所有注册的BeanFactoryPostProcessor bean,尊重明确的秩序,<p>必须在单例实例化之前调用。
            invokeBeanFactoryPostProcessors(beanFactory);
            //6、实例化并注册所有BeanPostProcessor bean,尊重明确的秩序。<p>必须在应用程序bean的任何实例化之前调用。
            registerBeanPostProcessors(beanFactory);
            //7、如果BeanFactory中存在一个叫做"messageSource"的BeanDefinition,那么就会把这个Bean对象创建出来并赋值给ApplicationContext的messageSource属性,让ApplicationContext拥有国际化的功能
            initMessageSource();
            //8、如果BeanFactory中存在一个叫做"applicationEventMulticaster"的BeanDefinition,那么就会把这个Bean对象创建出来并赋值给ApplicationContext的applicationEventMulticaster属性,让ApplicationContext拥有事件发布的功能
            initApplicationEventMulticaster();
            //9、提供给AbstractApplicationContext的子类进行扩展,没用
            onRefresh();
            //10、从BeanFactory中获取ApplicationListener类型的beanName,然后添加到ApplicationContext中的事件广播器applicationEventMulticaster中去,到这一步因为FactoryBean还没有调用getObject()方法生成Bean对象,所以这里要在根据类型找一下ApplicationListener,记录一下对应的beanName
            registerListeners();
            //11、完成BeanFactory的初始化,主要就是实例化非懒加载的单例Bean
            finishBeanFactoryInitialization(beanFactory);
            //12、BeanFactory的初始化完后,就到了Spring启动的最后一步了
            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.
            destroyBeans();
            // Reset 'active' flag.
            cancelRefresh(ex);
            // Propagate exception to caller.
            throw ex;
        }
        finally {
            // Reset common introspection caches in Spring's core, since we
            // might not ever need metadata for singleton beans anymore...
            resetCommonCaches();
        }
    }
}
View Code

2.1、prepareRefresh 具体代码逻辑

a、记录启动时间
b、initPropertySources()给子类提供实现的空方法,允许子容器设置一些变量到容器中
c、getEnvironment().validateRequiredProperties()初始化Environment环境变量,并验证是否包括了必须要有的属性
2.2、prepareBeanFactory(beanFactory)具体代码逻辑
a、使用beanFactory.setBeanClassLoader设置beanFactory的类加载器
b、使用beanFactory.setBeanExpressionResolver设置用来解析Spring中的表达式的解析器
c、使用beanFactory.addPropertyEditorRegistrar设置属性转化器
d、使用beanFactory.addBeanPostProcessor设置ApplicationContextAwareProcessor,ApplicationContextAwareProcessor用来执行EnvironmentAware、ApplicationEventPublisherAware等回调方法
e、使用beanFactory.ignoreDependencyInterface设置EnvironmentAware、EmbeddedValueResolverAware、ResourceLoaderAware、ApplicationEventPublisherAware、MessageSourceAware、ApplicationContextAware等接口,以EnvironmentAware为例,当实现EnvironmentAware,setEnvironment方法上存在@Autowired注解时,EnvironmentAware接口回调setEnvironment方法和@Autowired实现的spring自动注入存在冲突。使用beanFactory.ignoreDependencyInterface注入接口之后,就只等Aware接口回调再来调用
    @Autowired
    @Override
    public void setEnvironment(Environment environment) {
        System.out.println("打印environment===="+environment);
        this.environment = environment;
    }

 f、使用beanFactory.registerResolvableDependency注入BeanFactory,ResourceLoader,ApplicationEventPublisher,ApplicationContext,在byType进行依赖注入时,会先从resolvableDependency这个属性中根据类型找bean,代码如下:

protected void autowireByType(
            String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {
    ...
    for (String propertyName : propertyNames) {
        try {
            PropertyDescriptor pd = bw.getPropertyDescriptor(propertyName);
            // Don't try autowiring by type for type Object: never makes sense,
            // even if it technically is a unsatisfied, non-simple property.
            if (Object.class != pd.getPropertyType()) {
                MethodParameter methodParam = BeanUtils.getWriteMethodParameter(pd);
                // Do not allow eager init for type matching in case of a prioritized post-processor.
                boolean eager = !(bw.getWrappedInstance() instanceof PriorityOrdered);
                DependencyDescriptor desc = new AutowireByTypeDependencyDescriptor(methodParam, eager);
                //在byType进行依赖注入时,会先从这个属性中根据类型找bean
                Object autowiredArgument = resolveDependency(desc, beanName, autowiredBeanNames, converter);
                if (autowiredArgument != null) {
                    pvs.add(propertyName, autowiredArgument);
                }
                for (String autowiredBeanName : autowiredBeanNames) {
                    registerDependentBean(autowiredBeanName, beanName);
                    if (logger.isTraceEnabled()) {
                        logger.trace("Autowiring by type from bean name '" + beanName + "' via property '" +
                                propertyName + "' to bean named '" + autowiredBeanName + "'");
                    }
                }
                autowiredBeanNames.clear();
            }
        }
        ...
    }
}

g、使用beanFactory.registerSingleton注册默认环境bean

2.3、postProcessBeanFactory(beanFactory)具体代码逻辑

a、提供给AbstractApplicationContext的子类进行扩展,具体的子类,可以继续向BeanFactory中再添加一些东西
2.4、

2.3、其中refresh方法第12步,中具体执行逻辑如下

protected void finishRefresh() {
    //1、清除上下文级别的资源缓存(如扫描中的ASM元数据)
    clearResourceCaches();
    //2、设置ApplicationContext的lifecycleProcessor,默认情况下设置的是DefaultLifecycleProcessor
    initLifecycleProcessor();
    //3、调用lifecycleProcessor的onRefresh()方法,如果是DefaultLifecycleProcessor,那么会获取所
    //有类型为Lifecycle的Bean对象,然后调用它的start()方法,这就是ApplicationContext的生命周期扩展机制
    getLifecycleProcessor().onRefresh();
    //4、发布ContextRefreshedEvent事件
    publishEvent(new ContextRefreshedEvent(this));
    //5、如果处于活动状态,请参与LiveBeansView MBean
    LiveBeansView.registerApplicationContext(this);
}

 

posted @ 2023-05-09 16:37  西风51668  阅读(43)  评论(0)    收藏  举报