SpringBoot启动原理

启动流程

启动的整体流程如下图(引用自网络)
图片来源
在这里插入图片描述
启动中主要分为两步:

  • 1、实例化SpringApplication对象
    • 1.1 配置source
    • 1.2 从类路径中推断web应用类型
    • 1.3 设置初始化执行器,加载实现了ApplicationContextInitializer接口的类
    • 1.4 设置应用监听器,加载实现了ApplicationListener接口的类
    • 1.5 通过反射获取启动类
  • 2、调用SpringApplication的run方法
    • 2.1 启动计时器
    • 2.2 配置headless属性
    • 2.3 获取运行监听器 EventPublishingRunListener,启动监听器监听
    • 2.4 预备环境信息
    • 2.5 配置忽略的bean信息
    • 2.6 打印springboot图标
    • 2.7 创建应用上下文
    • 2.8 实例化异常报告器
    • 2.9 预备上下文
    • 2.10 刷新上下文,注册bean到IOC容器
    • 2.11 刷新上下文后处理
    • 2.12 停止计时器
    • 2.13 通知监听器:上下文已初始化
    • 2.14 执行实现了ApplicationRunner和CommandLineRunner接口的启动执行类
    • 2.15 发布ApplicationReadyEvent事件,通知监听器:应用已启动

具体的启动流程如下:

@SpringBootApplication
public class Application extends SpringBootServletInitializer {
    public static void main(String[] args) {
        // 新建SpringApplication
        SpringApplication app = new SpringApplication(Application.class);
        // 执行run方法
        app.run(args);
    }
}

@SpringBootApplication是@SpringBootConfiguration、@EnableAutoConfiguration、@ComponentScan三个注解的组合,可以提供SpringBoot配置,自动装配,组件扫描

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
      @Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {

   @AliasFor(annotation = EnableAutoConfiguration.class)
   Class<?>[] exclude() default {};

   @AliasFor(annotation = EnableAutoConfiguration.class)
   String[] excludeName() default {};

   @AliasFor(annotation = ComponentScan.class, attribute = "basePackages")
   String[] scanBasePackages() default {};

   @AliasFor(annotation = ComponentScan.class, attribute = "basePackageClasses")
   Class<?>[] scanBasePackageClasses() default {};

   @AliasFor(annotation = Configuration.class)
   boolean proxyBeanMethods() default true;

}

new SpringApplication(Application.class) 的实现中会创建一个SpringApplication实例,应用上下文会装在来自于特定基础来源的beans

@SuppressWarnings({ "unchecked", "rawtypes" })
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
   this.resourceLoader = resourceLoader;
   Assert.notNull(primarySources, "PrimarySources must not be null");
    // 基础源
   this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
    // 从类路径中推断web应用类型
   this.webApplicationType = WebApplicationType.deduceFromClasspath();
    // 设置初始化执行器,加载实现了ApplicationContextInitializer接口的类
   setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
    // 设置应用监听器,加载实现了ApplicationListener接口的类
   setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
    // 通过反射获取启动类
   this.mainApplicationClass = deduceMainApplicationClass();
}

getSpringFactoriesInstances 方法可以获取spring 工厂实例

private <T> Collection<T> getSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, Object... args) {
    // 获取类加载器
   ClassLoader classLoader = getClassLoader();
    // 将加载的factory名字去重放入set中
   Set<String> names = new LinkedHashSet<>(SpringFactoriesLoader.loadFactoryNames(type, classLoader));
    // 创建spring factory实例
   List<T> instances = createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names);
    // 排序
   AnnotationAwareOrderComparator.sort(instances);
   return instances;
}

getClassLoader会调用ClassUtils#getDefaultClassLoader来获取默认的类加载器,该加载器先获取当前线程的类加载器,如果没有获取到,再获取当前类的类加载器,如果还是没有获取到,再获取系统的类加载器

public static ClassLoader getDefaultClassLoader() {
   ClassLoader cl = null;
   try {
       // 当前线程的类加载器
      cl = Thread.currentThread().getContextClassLoader();
   } catch (Throwable ex) {
      // Cannot access thread context ClassLoader - falling back...
   }
   if (cl == null) {
       // 没有线程类加载器-》使用当前类的类加载器
      cl = ClassUtils.class.getClassLoader();
      if (cl == null) {
          // getClassLoader() 返回null,表示bootstrap类加载器
         try {
             // 系统的类加载器
            cl = ClassLoader.getSystemClassLoader();
         }
         catch (Throwable ex) {
            // Cannot access system ClassLoader - oh well, maybe the caller can live with null...
         }
      }
   }
   return cl;
}

SpringFactoriesLoader.loadFactoryNames(type, classLoader)会加载jar包的spring.factories中的配置类

private static Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader) {
    // 根据classLoader从缓存中获取已加载的配置类
   MultiValueMap<String, String> result = cache.get(classLoader);
   if (result != null) {
      return result;
   }

   try {
       // FACTORIES_RESOURCE_LOCATION="META-INF/spring.factories",获取项目中所有引用的jar包的spring.factories文件位置URL
      Enumeration<URL> urls = (classLoader != null ?
            classLoader.getResources(FACTORIES_RESOURCE_LOCATION) :
            ClassLoader.getSystemResources(FACTORIES_RESOURCE_LOCATION));
      result = new LinkedMultiValueMap<>();
      while (urls.hasMoreElements()) {
          //  加载具体的jar的spring.factories,如: jar:file:/D:/repository/org/springframework/spring-beans/5.2.5.RELEASE/spring-beans-5.2.5.RELEASE.jar!/META-INF/spring.factories
         URL url = urls.nextElement();
         UrlResource resource = new UrlResource(url);
          // 加载spring.factories文件中具体的配置项,文件内容是kv形式的
         Properties properties = PropertiesLoaderUtils.loadProperties(resource);
         for (Map.Entry<?, ?> entry : properties.entrySet()) {
             // 获取key
            String factoryTypeName = ((String) entry.getKey()).trim();
            for (String factoryImplementationName : StringUtils.commaDelimitedListToStringArray((String) entry.getValue())) {
               // 获取value,存入result
                result.add(factoryTypeName, factoryImplementationName.trim());
            }
         }
      }
       // 放入缓存
      cache.put(classLoader, result);
      return result;
   } catch (IOException ex) {
      throw new IllegalArgumentException("Unable to load factories from location [" +FACTORIES_RESOURCE_LOCATION + "]", ex);
   }
}

createSpringFactoriesInstances 根据new LinkedHashSet<>(SpringFactoriesLoader.loadFactoryNames(type, classLoader))获取的类名,通过反射的方式实例化类

private <T> List<T> createSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes,
      ClassLoader classLoader, Object[] args, Set<String> names) {
   List<T> instances = new ArrayList<>(names.size());
   for (String name : names) {
      try {
          // 反射获取类实例
         Class<?> instanceClass = ClassUtils.forName(name, classLoader);
         Assert.isAssignable(type, instanceClass);
          // 获取该类声明的构造器
         Constructor<?> constructor = instanceClass.getDeclaredConstructor(parameterTypes);
          // 使用声明的构造器和参数实例化类
         T instance = (T) BeanUtils.instantiateClass(constructor, args);
         instances.add(instance);
      } catch (Throwable ex) {
         throw new IllegalArgumentException("Cannot instantiate " + type + " : " + name, ex);
      }
   }
   return instances;
}

以上是new SpringApplication(Application.class)的创建过程,接着是调用该对象的run方法

public ConfigurableApplicationContext run(String... args) {
   StopWatch stopWatch = new StopWatch();
    // 启动计时器
   stopWatch.start();
   ConfigurableApplicationContext context = null;
   Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
   configureHeadlessProperty();
    // 获取运行监听器 EventPublishingRunListener
   SpringApplicationRunListeners listeners = getRunListeners(args);
    // 启动监听器监听
   listeners.starting();
   try {
      ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
       // 预备环境信息
      ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);
       // 配置忽略的bean信息
      configureIgnoreBeanInfo(environment);
       // 打印springboot图标
      Banner printedBanner = printBanner(environment);
       // 创建引用上下文
      context = createApplicationContext();
       // 实例化异常报告器
      exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class,
            new Class[] { ConfigurableApplicationContext.class }, context);
       // 预备上下文
      prepareContext(context, environment, listeners, applicationArguments, printedBanner);
       // 刷新上下文,注册bean到IOC容器
      refreshContext(context);
      afterRefresh(context, applicationArguments);
      stopWatch.stop();
      if (this.logStartupInfo) {
         new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);
      }
       // 通知监听器:上下文已初始化
      listeners.started(context);
       // 执行实现了ApplicationRunner和CommandLineRunner接口的启动执行类
      callRunners(context, applicationArguments);
   } catch (Throwable ex) {
      handleRunFailure(context, ex, exceptionReporters, listeners);
      throw new IllegalStateException(ex);
   }

   try {
       // 发布ApplicationReadyEvent事件,通知监听器:应用已启动
      listeners.running(context);
   }catch (Throwable ex) {
      handleRunFailure(context, ex, exceptionReporters, null);
      throw new IllegalStateException(ex);
   }
   return context;
}

listeners.starting()启动监听器会调用SpringApplicationRunListener#starting方法,这里的listener主要是EventPublishingRunListener

void starting() {
   for (SpringApplicationRunListener listener : this.listeners) {
      listener.starting();
   }
}

EventPublishingRunListener#starting会调用广播事件方法multicastEvent,

public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {
    // 事件类型
   ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
    // 任务执行器
   Executor executor = getTaskExecutor();
    // getApplicationListeners(event, type)获取该类型事件的所有监听器
   for (ApplicationListener<?> listener : getApplicationListeners(event, type)) {
      if (executor != null) { // 使用执行器调用监听器
         executor.execute(() -> invokeListener(listener, event));
      }
      else { // 不使用执行器调用监听器
         invokeListener(listener, event);
      }
   }
}

invokeListener(listener, event)跟着会调用SimpleApplicationEventMulticaster#doInvokeListener

private void doInvokeListener(ApplicationListener listener, ApplicationEvent event) {
   try {
       // 监听器监听到事件执行业务逻辑
      listener.onApplicationEvent(event);
   } catch (ClassCastException ex) {
      String msg = ex.getMessage();
      if (msg == null || matchesClassCastMessage(msg, event.getClass())) {
         // Possibly a lambda-defined listener which we could not resolve the generic event type for
         // -> let's suppress the exception and just log a debug message.
         Log logger = LogFactory.getLog(getClass());
         if (logger.isTraceEnabled()) {
            logger.trace("Non-matching event type for listener: " + listener, ex);
         }
      }
      else {
         throw ex;
      }
   }
}

prepareEnvironment(listeners, applicationArguments)准备环境信息

private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners,
      ApplicationArguments applicationArguments) {
   // 创建和配置环境
   ConfigurableEnvironment environment = getOrCreateEnvironment();
   // 配置环境信息,配置文件相关信息加载
   configureEnvironment(environment, applicationArguments.getSourceArgs());
    // 绑定环境信息到配置属性源
   ConfigurationPropertySources.attach(environment);
    // 通知监听器:环境信息已加载
   listeners.environmentPrepared(environment);
    // 绑定到SpringApplication
   bindToSpringApplication(environment);
    // 定制化环境信息
   if (!this.isCustomEnvironment) {
      environment = new EnvironmentConverter(getClassLoader()).convertEnvironmentIfNecessary(environment,
            deduceEnvironmentClass());
   }
    // 再次绑定环境信息到配置属性源
   ConfigurationPropertySources.attach(environment);
   return environment;
}

createApplicationContext()创建应用上下文,根据不同的web应用类型,通过反射获取合适类型的上下文进行实例化

protected ConfigurableApplicationContext createApplicationContext() {
   Class<?> contextClass = this.applicationContextClass;
   if (contextClass == null) {
      try {
         switch (this.webApplicationType) {
         case SERVLET: 
                 // 反射获取类对象
            contextClass = Class.forName(DEFAULT_SERVLET_WEB_CONTEXT_CLASS);
            break;
         case REACTIVE:
            contextClass = Class.forName(DEFAULT_REACTIVE_WEB_CONTEXT_CLASS);
            break;
         default:
            contextClass = Class.forName(DEFAULT_CONTEXT_CLASS);
         }
      }
      catch (ClassNotFoundException ex) {
         throw new IllegalStateException(
               "Unable create a default ApplicationContext, please specify an ApplicationContextClass", ex);
      }
   }
    // 根据类的基本构造方法或默认构造方法实例化一个对象
   return (ConfigurableApplicationContext) BeanUtils.instantiateClass(contextClass);
}

prepareContext

private void prepareContext(ConfigurableApplicationContext context, ConfigurableEnvironment environment,
      SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments, Banner printedBanner) {
   context.setEnvironment(environment);
    // 应用上下文后处理
   postProcessApplicationContext(context);
    // 应用初始化器
   applyInitializers(context);
    // 通知监听器上下文已经准备好
   listeners.contextPrepared(context);
    // 打印启动信息
   if (this.logStartupInfo) {
      logStartupInfo(context.getParent() == null);
      logStartupProfileInfo(context);
   }
   // 添加具体的单例bean
   ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
    // 注册springApplicationArguments单例bean
   beanFactory.registerSingleton("springApplicationArguments", applicationArguments);
   if (printedBanner != null) {
      beanFactory.registerSingleton("springBootBanner", printedBanner);
   }
   if (beanFactory instanceof DefaultListableBeanFactory) {
       // 设置允许bean定义覆盖
      ((DefaultListableBeanFactory) beanFactory).setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
   }
   if (this.lazyInitialization) { // 设置懒加载
      context.addBeanFactoryPostProcessor(new LazyInitializationBeanFactoryPostProcessor());
   }
   // 加载源sources
   Set<Object> sources = getAllSources();
   Assert.notEmpty(sources, "Sources must not be empty");
    // 加载启动类的bean到IOC容器
   load(context, sources.toArray(new Object[0]));
    // 通知监听器上下文已加载
   listeners.contextLoaded(context);
}

load(context, sources.toArray(new Object[0]))加载bean到IOC容器的具体流程如下

protected void load(ApplicationContext context, Object[] sources) {
   if (logger.isDebugEnabled()) {
      logger.debug("Loading source " + StringUtils.arrayToCommaDelimitedString(sources));
   }
    // 创建bean加载器
   BeanDefinitionLoader loader = createBeanDefinitionLoader(getBeanDefinitionRegistry(context), sources);
   if (this.beanNameGenerator != null) {
      loader.setBeanNameGenerator(this.beanNameGenerator);
   }
   if (this.resourceLoader != null) {
      loader.setResourceLoader(this.resourceLoader);
   }
   if (this.environment != null) {
      loader.setEnvironment(this.environment);
   }
    // 使用bean加载器加载bean
   loader.load();
}

BeanDefinitionLoader#load()会先加载组件bean

private int load(Class<?> source) {
   if (isGroovyPresent() && GroovyBeanDefinitionSource.class.isAssignableFrom(source)) {
      // Any GroovyLoaders added in beans{} DSL can contribute beans here
      GroovyBeanDefinitionSource loader = BeanUtils.instantiateClass(source, GroovyBeanDefinitionSource.class);
      load(loader);
   }
    // 组件bean加载
   if (isComponent(source)) {
       // 注册source
      this.annotatedReader.register(source);
      return 1;
   }
   return 0;
}

AnnotatedGenericBeanDefinition#register 进行实际的bean注册

public void register(Class<?>... componentClasses) {
   for (Class<?> componentClass : componentClasses) {
      registerBean(componentClass);
   }
}

public void registerBean(Class<?> beanClass) {
		doRegisterBean(beanClass, null, null, null, null);
}

重头戏:doRegisterBean 完成实际的bean注册。

private <T> void doRegisterBean(Class<T> beanClass, @Nullable String name,
      @Nullable Class<? extends Annotation>[] qualifiers, @Nullable Supplier<T> supplier,
      @Nullable BeanDefinitionCustomizer[] customizers) {
   // 为给定的bean class创建一个AnnotatedGenericBeanDefinition
   AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(beanClass);
    // 基于@Conditional注解判断一个bean是否要跳过
   if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
      return;
   }

   abd.setInstanceSupplier(supplier);
    // 解析范围元数据
   ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
   abd.setScope(scopeMetadata.getScopeName());
    // 获取beanName, 默认是类名的首字母小写
   String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));
   // 处理通用定义注解
   AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);
   if (qualifiers != null) {
      for (Class<? extends Annotation> qualifier : qualifiers) {
         if (Primary.class == qualifier) {
            abd.setPrimary(true);
         }
         else if (Lazy.class == qualifier) {
            abd.setLazyInit(true);
         }
         else {
            abd.addQualifier(new AutowireCandidateQualifier(qualifier));
         }
      }
   }
   if (customizers != null) {
      for (BeanDefinitionCustomizer customizer : customizers) {
         customizer.customize(abd);
      }
   }

   BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
    // 范围代理模式处理,一般是NO
   definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
    // 注册bean
   BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
}

BeanDefinitionReaderUtils.registerBeanDefinition会将bean注册到上下文的bean factory里面

public static void registerBeanDefinition(
      BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
      throws BeanDefinitionStoreException {

   // Register bean definition under primary name.
   String beanName = definitionHolder.getBeanName();
    // 注册bean定义
   registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());

   // 注册bean别名,如果有
   String[] aliases = definitionHolder.getAliases();
   if (aliases != null) {
      for (String alias : aliases) {
         registry.registerAlias(beanName, alias);
      }
   }
}

listeners.contextLoaded(context)会调用到EventPublishingRunListener#contextLoaded方法

public void contextLoaded(ConfigurableApplicationContext context) {
   for (ApplicationListener<?> listener : this.application.getListeners()) {
       // 如果监听器实现了ApplicationContextAware接口,就会执行上下文初始化
      if (listener instanceof ApplicationContextAware) {
         ((ApplicationContextAware) listener).setApplicationContext(context);
      }
       // 上下文中添加监听器
      context.addApplicationListener(listener);
   }
    // 广播应用已经准备好事件
   this.initialMulticaster.multicastEvent(new ApplicationPreparedEvent(this.application, this.args, context));
}

run#refreshContext会刷新上下文

private void refreshContext(ConfigurableApplicationContext context) {
   refresh(context);
   if (this.registerShutdownHook) {
      try {
         context.registerShutdownHook();
      }
      catch (AccessControlException ex) {
         // Not allowed in some environments.
      }
   }
}

该方法会调用AbstractApplicationContext#refresh

public void refresh() throws BeansException, IllegalStateException {
   synchronized (this.startupShutdownMonitor) {
      // Prepare this context for refreshing.
       // 为刷新准备上下文
      prepareRefresh();

      // Tell the subclass to refresh the internal bean factory.
       // 告诉子类去刷新内部的bean factory
      ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

      // Prepare the bean factory for use in this context.
       // 在此上下文中准备bean factory
      prepareBeanFactory(beanFactory);

      try {
         // Allows post-processing of the bean factory in context subclasses.
         postProcessBeanFactory(beanFactory);

         // Invoke factory processors registered as beans in the context.
         invokeBeanFactoryPostProcessors(beanFactory);

         // Register bean processors that intercept bean creation.
         registerBeanPostProcessors(beanFactory);

         // Initialize message source for this context.
         initMessageSource();

         // Initialize event multicaster for this context.
         initApplicationEventMulticaster();

         // Initialize other special beans in specific context subclasses.
         onRefresh();

         // Check for listener beans and register them.
         registerListeners();

         // 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);
         }

         // 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();
      }
   }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值