• SpringBoot 启动流程


    SpringBoot 启动流程

    • 加载 resources/META-INF/spring.factories 中配置的 ApplicationContextInitializer 和 ApplicationListener。
    /**
     *  加载在框架内部使用的各种通用工厂 bean。
     *  spring.factories 文件必须满足 Properties 文件格式,属性的 key 是接口或抽象类的全限定类名,
     *  value 是一组由逗号分隔的实现类全类名。
     */
    public final class SpringFactoriesLoader {
        /**
         *  工厂 bean 的搜索路径,可以在多个 jar 文件中出现 spring.factories 文件。
         */
        public static final String FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories";
    
        private static final Log logger = LogFactory.getLog(SpringFactoriesLoader.class);
    
        private static final Map<ClassLoader, MultiValueMap<String, String>> cache = new ConcurrentReferenceHashMap<>();
    
        private SpringFactoriesLoader() {
        }
    
        /**
         *  使用给定的类加载器,加载并实例化目标路径 FACTORIES_RESOURCE_LOCATION 下特定接口的实现类,
         *  或抽象类的子类。创建的类实例根据 AnnotationAwareOrderComparator 进行排序。
         */
        public static <T> List<T> loadFactories(Class<T> factoryClass, @Nullable ClassLoader classLoader) {
            Assert.notNull(factoryClass, "'factoryClass' must not be null");
            ClassLoader classLoaderToUse = classLoader;
            if (classLoaderToUse == null) {
                classLoaderToUse = SpringFactoriesLoader.class.getClassLoader();
            }
            final List<String> factoryNames = loadFactoryNames(factoryClass, classLoaderToUse);
            if (logger.isTraceEnabled()) {
                logger.trace("Loaded [" + factoryClass.getName() + "] names: " + factoryNames);
            }
            final List<T> result = new ArrayList<>(factoryNames.size());
            for (final String factoryName : factoryNames) {
                result.add(instantiateFactory(factoryName, factoryClass, classLoaderToUse));
            }
            AnnotationAwareOrderComparator.sort(result);
            return result;
        }
    
        /**
         *  使用指定的类加载器,加载 FACTORIES_RESOURCE_LOCATION 路径下指定类型的 factory 全类名。
         */
        public static List<String> loadFactoryNames(Class<?> factoryClass, @Nullable ClassLoader classLoader) {
            // 获取目标 factory 全类名
            final String factoryClassName = factoryClass.getName();
            // 加载所有配置文件,并读取指定 factory 的实现类列表
            return loadSpringFactories(classLoader).getOrDefault(factoryClassName, Collections.emptyList());
        }
    
        private static Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader) {
            // 如果已经加载了 spring.factories 文件,则直接从缓存中获取
            MultiValueMap<String, String> result = cache.get(classLoader);
            if (result != null) {
                return result;
            }
    
            try {
                // 读取资源 URL
                final Enumeration<URL> urls = classLoader != null ?
                        classLoader.getResources(FACTORIES_RESOURCE_LOCATION) :
                            ClassLoader.getSystemResources(FACTORIES_RESOURCE_LOCATION);
                        result = new LinkedMultiValueMap<>();
                        while (urls.hasMoreElements()) {
                            final URL url = urls.nextElement();
                            final UrlResource resource = new UrlResource(url);
                            // 将资源加载到 Properties 文件中
                            final Properties properties = PropertiesLoaderUtils.loadProperties(resource);
                            for (final Map.Entry<?, ?> entry : properties.entrySet()) {
                                // 提取 factory 类名称作为 key
                                final String factoryClassName = ((String) entry.getKey()).trim();
                                /**
                                 *  将配置的实现类按照 , 分隔,添加到 LinkedMultiValueMap 中。
                                 *  内部通过 LinkedList 管理相同 factory 名称的各种实现类。
                                 */
                                for (final String factoryName : StringUtils.commaDelimitedListToStringArray((String) entry.getValue())) {
                                    result.add(factoryClassName, factoryName.trim());
                                }
                            }
                        }
                        // 加入缓存
                        cache.put(classLoader, result);
                        return result;
            }
            catch (final IOException ex) {
                throw new IllegalArgumentException("Unable to load factories from location [" +
                        FACTORIES_RESOURCE_LOCATION + "]", ex);
            }
        }
    
        @SuppressWarnings("unchecked")
        private static <T> T instantiateFactory(String instanceClassName, Class<T> factoryClass, ClassLoader classLoader) {
            try {
                final Class<?> instanceClass = ClassUtils.forName(instanceClassName, classLoader);
                if (!factoryClass.isAssignableFrom(instanceClass)) {
                    throw new IllegalArgumentException(
                            "Class [" + instanceClassName + "] is not assignable to [" + factoryClass.getName() + "]");
                }
                return (T) ReflectionUtils.accessibleConstructor(instanceClass).newInstance();
            }
            catch (final Throwable ex) {
                throw new IllegalArgumentException("Unable to instantiate factory class: " + factoryClass.getName(), ex);
            }
        }
    
    }
    
    • 加载 resources/META-INF/spring.factories 中配置的 SpringApplicationRunListener
    /**
     *  SpringApplication 监听器,必须提供一个接受命令行参数 String[] 的
     *  public 构造函数完成实例的初始化。
     */
    public interface SpringApplicationRunListener {
    
        /**
         *  1)加载完 SpringApplicationRunListener 实例后立即执行的方法,在 Application 初始化早期使用。
         */
        void starting();
    
        /**
         *  2)environment 准备好时调用,在 ApplicationContext 创建之前。
         */
        void environmentPrepared(ConfigurableEnvironment environment);
    
        /**
         *  3)在 ApplicationContext 创建并准备好时调用,此时资源还未加载。
         */
        void contextPrepared(ConfigurableApplicationContext context);
    
        /**
         *  4)ApplicationContext 加载完成之后调用,但是 ApplicationContext 还未刷新。
         *  组件扫描还未执行,BeanDefinition 还未注册。
         */
        void contextLoaded(ConfigurableApplicationContext context);
    
        /**
         *  5)ApplicationContext 已经刷新并启动,但还未执行 CommandLineRunner 和 ApplicationRunner。
         */
        void started(ConfigurableApplicationContext context);
    
        /**
         *  6)ApplicationContext 已经刷新并启动,所有的CommandLineRunner 和 ApplicationRunner 都已经执行。
         */
        void running(ConfigurableApplicationContext context);
    
        /**
         *  运行此 ApplicationContext 过程中出现异常
         */
        void failed(ConfigurableApplicationContext context, Throwable exception);
    }
    
    /**
     *  用于发布 SpringApplicationEvent 的 SpringApplicationRunListener
     */
    public class EventPublishingRunListener implements SpringApplicationRunListener, Ordered {
        /**
         *  目标应用程序
         */
        private final SpringApplication application;
    
        /**
         *  命令行参数
         */
        private final String[] args;
    
        /**
         *  简单的应用事件广播器
         */
        private final SimpleApplicationEventMulticaster initialMulticaster;
    
        public EventPublishingRunListener(SpringApplication application, String[] args) {
            this.application = application;
            this.args = args;
            initialMulticaster = new SimpleApplicationEventMulticaster();
            for (final ApplicationListener<?> listener : application.getListeners()) {
                initialMulticaster.addApplicationListener(listener);
            }
        }
    
        @Override
        public int getOrder() {
            return 0;
        }
    
        @Override
        public void starting() {
            initialMulticaster.multicastEvent(
                    new ApplicationStartingEvent(application, args));
        }
    
        @Override
        public void environmentPrepared(ConfigurableEnvironment environment) {
            initialMulticaster.multicastEvent(new ApplicationEnvironmentPreparedEvent(
                    application, args, environment));
        }
    
        @Override
        public void contextPrepared(ConfigurableApplicationContext context) {
            initialMulticaster.multicastEvent(new ApplicationContextInitializedEvent(
                    application, args, context));
        }
    
        @Override
        public void contextLoaded(ConfigurableApplicationContext context) {
            for (final ApplicationListener<?> listener : application.getListeners()) {
                if (listener instanceof ApplicationContextAware) {
                    ((ApplicationContextAware) listener).setApplicationContext(context);
                }
                context.addApplicationListener(listener);
            }
            initialMulticaster.multicastEvent(
                    new ApplicationPreparedEvent(application, args, context));
        }
    
        @Override
        public void started(ConfigurableApplicationContext context) {
            context.publishEvent(
                    new ApplicationStartedEvent(application, args, context));
        }
    
        @Override
        public void running(ConfigurableApplicationContext context) {
            context.publishEvent(
                    new ApplicationReadyEvent(application, args, context));
        }
    
        @Override
        public void failed(ConfigurableApplicationContext context, Throwable exception) {
            final ApplicationFailedEvent event = new ApplicationFailedEvent(application,
                    args, context, exception);
            if (context != null && context.isActive()) {
                // Listeners have been registered to the application context so we should
                // use it at this point if we can
                context.publishEvent(event);
            }
            else {
                // An inactive context may not have a multicaster so we use our multicaster to
                // call all of the context's listeners instead
                if (context instanceof AbstractApplicationContext) {
                    for (final ApplicationListener<?> listener : ((AbstractApplicationContext) context)
                            .getApplicationListeners()) {
                        initialMulticaster.addApplicationListener(listener);
                    }
                }
                initialMulticaster.setErrorHandler(new LoggingErrorHandler());
                initialMulticaster.multicastEvent(event);
            }
        }
    
        private static class LoggingErrorHandler implements ErrorHandler {
            private static Log logger = LogFactory.getLog(EventPublishingRunListener.class);
    
            @Override
            public void handleError(Throwable throwable) {
                logger.warn("Error calling ApplicationEventListener", throwable);
            }
        }
    }
    
    • 创建 StandardServletEnvironment 并完成初始配置。
    1)写入转换服务 ApplicationConversionService.getSharedInstance()
    2)将命令行参数作为属性源加入到 environment.getPropertySources() 中
    3)写入配置的 AdditionalProfile。
    
    • 通过 EventPublishingRunListener 发布 ApplicationEnvironmentPreparedEvent 事件

    • 加载 resources/META-INF/spring.factories 中配置的 EnvironmentPostProcessor,
      并触发其 postProcessEnvironment 调用,完成 Environment 的后处理【主要用于加载属性源到 Environment 中】。

    • 将 Environment 绑定到 SpringApplication 中。

    • 创建 ApplicationContext:AnnotationConfigServletWebServerApplicationContext

    • 加载 resources/META-INF/spring.factories 中配置的 SpringBootExceptionReporter【FailureAnalyzers】

    • 执行所有已加载的 ApplicationContextInitializer,附加自定义配置。

    • 通过 EventPublishingRunListener 发布 ApplicationContextInitializedEvent 事件

    • 创建 BeanDefinitionLoader,将应用程序主类解析为 BeanDefinition 并注册到 DefaultListableBeanFactory 中。

    @Lazy:此 Bean 是否延迟初始化
    @DependsOn:此 Bean 是否需要依赖其他 Bean
    @Role:此 Bean 的组件角色
    @Description:此 Bean 的描述信息
    @Scope:bean 的代理默认和作用域
    @Primary:依赖注入时存在多个候选 bean 时,优先注入此 bean
    
    • 通过 EventPublishingRunListener 发布 ApplicationPreparedEvent 事件。

    刷新此 ApplicationContext: AbstractApplicationContext#refresh()

    AbstractApplicationContext#
        @Override
        public void refresh() throws BeansException, IllegalStateException {
            synchronized (startupShutdownMonitor) {
                // 1)准备刷新上下文
                prepareRefresh();
    
                // 2)通知子类刷新内部的 ConfigurableListableBeanFactory
                final ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
    
                // 3)准备在此 ApplicationContext 中使用的 BeanFactory
                prepareBeanFactory(beanFactory);
    
                try {
                    // 4)允许在 ApplicationContext 中对 BeanFactory 进行后处理
                    postProcessBeanFactory(beanFactory);
    
                    // 5)执行注册在当前 ApplicationContext 中的 beanFactory 后处理器
                    invokeBeanFactoryPostProcessors(beanFactory);
    
                    // 6)将 BeanPostProcessor 注册到容器中
                    registerBeanPostProcessors(beanFactory);
    
                    // 7)初始化 MessageSource
                    initMessageSource();
    
                    // 8)初始化 SimpleApplicationEventMulticaster,用于实现事件发布
                    initApplicationEventMulticaster();
    
                    // 9)初始化其他特殊的 bean
                    onRefresh();
    
                    // 10)注册 ApplicationListener
                    registerListeners();
    
                    // 11)实例化所有非延迟的单例类
                    finishBeanFactoryInitialization(beanFactory);
    
                    // 12)清理资源缓存,初始化 LifecycleProcessor,并发布相关事件
                    finishRefresh();
                }
    
                catch (final BeansException ex) {
                    if (logger.isWarnEnabled()) {
                        logger.warn("Exception encountered during context initialization - " +
                                "cancelling refresh attempt: " + ex);
                    }
    
                    // 13)删除已经实例化的单例,避免资源泄漏
                    destroyBeans();
    
                    // 14)设置 active 标识
                    cancelRefresh(ex);
    
                    // 15)传播异常到外部
                    throw ex;
                }
    
                finally {
                    // 16)重设通用的缓存
                    resetCommonCaches();
                }
            }
        }
    
    • prepareRefresh:清除类路径扫描器缓存、写入 closed、active 标识、验证所有必须的属性是否都能解析。

    • obtainFreshBeanFactory:写入 refreshed 标识,获取 DefaultListableBeanFactory。

    • prepareBeanFactory:写入 BeanPostProcessor、写入可以忽略的依赖注入接口,注册部分内部可解析的依赖接口等。

    • postProcessBeanFactory:注册 WebApplicationScope,注册部分内部可解析的依赖接口。

    • invokeBeanFactoryPostProcessors:
      执行 SharedMetadataReaderFactoryContextInitializer$CachingMetadataReaderFactoryPostProcessor
      注册用于获取 MetadataReader 的 org.springframework.boot.autoconfigure.internalCachingMetadataReaderFactory 的 BeanDefinition。

    实例化并执行所有的 BeanDefinitionRegistryPostProcessor【内部只注册了 ConfigurationClassPostProcessor】:
    1)执行所有实现 PriorityOrdered 接口的 BeanDefinitionRegistry 后处理器【可以通过自定义 ApplicationContextInitializer 注册】。
        实例化并注册用于解析配置类的解析器【ConfigurationClassPostProcessor】:org.springframework.context.annotation.internalConfigurationAnnotationProcessor。
        使用 ConfigurationClassParser 解析主配置类并执行 ComponentScan、执行自动配置类的解析、各种导入 XML 文件的解析,将相关所有类的 BeanDefinition 
        注册到 DefaultListableBeanFactory 中。
    2)执行所有实现 Ordered 接口的 BeanDefinitionRegistry 后处理器。
    3)执行所有普通的 BeanDefinitionRegistry 后处理器。
    
    1)实例化并顺序执行以下内置的 BeanFactoryPostProcessor 后处理器
    无操作:org.springframework.boot.autoconfigure.SharedMetadataReaderFactoryContextInitializer$CachingMetadataReaderFactoryPostProcessor
    无操作:org.springframework.boot.context.ConfigurationWarningsApplicationContextInitializer$ConfigurationWarningsPostProcessor
    使用 ConfigurationClassEnhancer 强化所有的配置类:org.springframework.context.annotation.ConfigurationClassPostProcessor
    org.springframework.boot.context.config.ConfigFileApplicationListener$PropertySourceOrderingPostProcessor
    2)
    执行实现 PriorityOrdered 接口的 BeanFactoryPostProcessor 后处理器。
    执行实现 Ordered 接口的 BeanFactoryPostProcessor 后处理器。
    执行普通的 BeanFactoryPostProcessor 后处理器。
    
    • registerBeanPostProcessors:
      按照 【PriorityOrdered、Ordered、普通】的顺序将 BeanPostProcessor 添加到 BeanFactory 中。
    org.springframework.context.support.ApplicationContextAwareProcessor
    org.springframework.boot.web.servlet.context.WebApplicationContextServletContextAwareProcessor org.springframework.context.annotation.ConfigurationClassPostProcessor$ImportAwareBeanPostProcessor
    org.springframework.context.support.PostProcessorRegistrationDelegate$BeanPostProcessorChecker
    org.springframework.boot.context.properties.ConfigurationPropertiesBindingPostProcessor
    org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator
    org.springframework.validation.beanvalidation.MethodValidationPostProcessor
    org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor
    org.springframework.boot.web.server.WebServerFactoryCustomizerBeanPostProcessor
    org.springframework.boot.web.server.ErrorPageRegistrarBeanPostProcessor
    org.springframework.context.annotation.CommonAnnotationBeanPostProcessor
    org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor
    org.springframework.context.support.ApplicationListenerDetector
    
    • initMessageSource:注册 messageSource 单例【DelegatingMessageSource】

    • 注册 applicationEventMulticaster 单例【SimpleApplicationEventMulticaster】,用于广播 ApplicationEvent。

    • onRefresh:设置主题,创建内嵌服务器【WebServer】,获取 ServletContextInitializer【DispatcherServletRegistrationBean】
      初始化器并注册 DispatcherServlet 到 javax.servlet.ServletContext 和 org.apache.catalina.core.ApplicationContext 中。
      注册 OrderedCharacterEncodingFilter、OrderedHiddenHttpMethodFilter、OrderedFormContentFilter、OrderedRequestContextFilter
      等过滤器,也可注册自定义过滤器。
      写入 ServletContextPropertySource、ServletConfigPropertySource 到 Environment 中。

    • registerListeners:注册内置的 ApplicationListener、自定义的 ApplicationListener 到 ApplicationEventMulticaster 中。

    • finishBeanFactoryInitialization:冻结 DefaultListableBeanFactory 中注册的 BeanDefinition 信息,并实例化所有非延迟初始化的单例 bean。
      在所有 eager 单例初始化完成之后,如果其实现了 SmartInitializingSingleton 接口,则触发其 afterSingletonsInstantiated 调用完成后处理。

    bean 的实例化过程:
    1)优先实例化所有其依赖的 bean
    2)执行 InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation 预处理,
    如果该方法手动创建了 bean,则直接返回,不进入框架创建 bean 的主流程。
    3)实例化 bean
    4)执行 MergedBeanDefinitionPostProcessor#postProcessMergedBeanDefinition 后处理,
    AutowiredAnnotationBeanPostProcessor:解析 @Autowired、@Value、@Inject【JSR303】 注解元数据并缓存。
    CommonAnnotationBeanPostProcessor:解析 @PostConstruct、@PreDestroy 注解并将目标方法加入 BeanDefinition 中,解析 @Resource 注解元数据并缓存。
    5)将此 bean 加入到 singletonFactories 缓存中,以解决循环依赖问题。
    6)执行 InstantiationAwareBeanPostProcessor#postProcessAfterInstantiation 后处理,
    如果该方法完成了 bean 的依赖属性注入并返回 false,则跳过框架的属性注入流程。
    7)执行 InstantiationAwareBeanPostProcessor#postProcessProperties 依赖属性注入【直接属性注入、set 方法注入】。
    @Resource、@Autowired、@Value、@Inject【JSR303】
    8)执行其他方式的属性依赖注入,如 XML 配置方式。
    9)执行 BeanNameAware、BeanClassLoaderAware、BeanFactoryAware 注入。
    10)触发 BeanPostProcessor#postProcessBeforeInitialization 调用,
    ApplicationContextAwareProcessor:EnvironmentAware、EmbeddedValueResolverAware、ResourceLoaderAware、ApplicationEventPublisherAware、MessageSourceAware、ApplicationContextAware 注入。
    ServletContextAwareProcessor:ServletContextAware、ServletConfigAware 注入。
    11)执行 InitializingBean#afterPropertiesSet 调用,执行自定义的初始化方法。
    12)执行 BeanPostProcessor#postProcessAfterInitialization 调用。
    AnnotationAwareAspectJAutoProxyCreator:目标类型上存在 AspectJ 切面注解、目标类型能匹配 Spring 内置的 Advisor【缓存通知、事务处理】,则为目标 bean 创建代理。
    MethodValidationPostProcessor:目标类型上存在 @Validated 注解,方法参数或返回类型上存在 JSR303 校验约束,则为目标 bean 创建代理。
    PersistenceExceptionTranslationPostProcessor:如果目标类型实现了 org.springframework.dao.support.PersistenceExceptionTranslator 接口,
    则将本地资源异常转换为 DataAccessException。
    ApplicationListenerDetector:目标 bean 实现了 ApplicationListener 接口,则将其加入到 AbstractApplicationContext.applicationListeners 中。
    
    • 注册 DefaultLifecycleProcessor,查找所有实现 SmartLifecycle 接口的 bean && 如果它是 isAutoStartup(),则触发其 start() 方法调用。

    • 通过 EventPublishingRunListener 发布 ContextRefreshedEvent 事件。

    • 启动 WebServer。

    • 通过 EventPublishingRunListener 发布 ServletWebServerInitializedEvent 事件。

    • 清理各种缓存

    ReflectionUtils.clearCache();
    AnnotationUtils.clearCache();
    ResolvableType.clearCache();
    CachedIntrospectionResults.clearClassLoader(getClassLoader());
    
    • 注册 Application 的 ShutdownHook。

    • 触发 SpringApplicationRunListener 的 started 通知。

    • 通过 EventPublishingRunListener 发布 ApplicationStartedEvent 事件。

    • 按照 Order 对 ApplicationRunner、CommandLineRunner 进行排序,并顺序执行。

    • 触发 SpringApplicationRunListener 的 running 通知。

    • 通过 EventPublishingRunListener 发布 ApplicationReadyEvent 事件。

    • 应用程序启动完成。

  • 相关阅读:
    抽象类与接口的区别
    模板模式(Template Pattern)
    KVM虚拟化
    find文本处理(locate)实例学习记录
    AWK-文本处理测试实例记录
    Linux系统中如何查找大文件
    吞吐量和Iops、测试工具FIO使用
    linux了解
    了解docker
    语言资源国际化
  • 原文地址:https://www.cnblogs.com/zhuxudong/p/10357137.html
Copyright © 2020-2023  润新知