springboot启动流程源码分析

224 阅读3分钟
@SpringBootApplication
public class SpringBootDemoApplication {

	public static void main(String[] args) {
		SpringApplication.run(SpringBootDemoApplication.class, args);
	}

}

SpringApplication类的静态run方法,primarySource 这个类很关键,后面进行BFPP进行操作的时候,需要对这个类型上面的注解进行解析,这就是为啥springBoot正常情况下只能扫描启动类当前的包和子包的类进行IOC管理。

public static ConfigurableApplicationContext run(Class<?> primarySource, String... args) {
   return run(new Class<?>[] { primarySource }, args);
}
public static ConfigurableApplicationContext run(Class<?>[] primarySources, String[] args) {
    return new SpringApplication(primarySources).run(args);
}

SpringApplication的核心构造方法

public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
   this.resourceLoader = resourceLoader;
   Assert.notNull(primarySources, "PrimarySources must not be null");
   // springboot项目的启动类,一切资源的基础
   this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
    // webApplicationType的类型,根据类加载器是否存在相应的类来判断类型,来决定web容器的类型;NONE,SERVLET,REACTIVE
   this.webApplicationType = WebApplicationType.deduceFromClasspath();
    // 从MATE-INF/spring.factories 中查找是否有BootstrapRegistryInitializer类型的类,进行初始化
   this.bootstrapRegistryInitializers = new ArrayList<>(
         getSpringFactoriesInstances(BootstrapRegistryInitializer.class));
    // 从spring.factories中加载 ApplicationContextInitializer 类型的类
   setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
    // 加载了 ApplicationListener 
   setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
    // 以上3个都是可以进行扩展的地方
    // 获取启动main方法的类
   this.mainApplicationClass = deduceMainApplicationClass();
}

SpringApplication的实例方法--run

public ConfigurableApplicationContext run(String... args) {
		long startTime = System.nanoTime();
        // 创建DefaultBootstrapContext 类,并使用构造函数中注册的BootstrapRegistryInitializer 实例对bootstrapContext 进行初始化操作,可以进行一些逻辑的操作
		DefaultBootstrapContext bootstrapContext = createBootstrapContext();
		ConfigurableApplicationContext context = null;
        // java.awt.headless 参数设置
		configureHeadlessProperty();
        // 从MATE-INF/spring.factories文件中获取 SpringApplicationRunListener 类型的实例进行,包装在 listeners 中
        // 默认listeners中只有一个 EventPublishingRunListener
		SpringApplicationRunListeners listeners = getRunListeners(args);
    	// 对监听中中 SpringApplicationRunListener变量进行starting方法,默认实现使用多播器发布一个 ApplicationStartingEvent 的事件。
        // 这里使用业务自定义的监听器监听没有效果,因为这个spring容器还没有初始化,对于的Bean还没有创建
		listeners.starting(bootstrapContext, this.mainApplicationClass);
		try {
            // 参数包装
			ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
            // environment环境构建
			ConfigurableEnvironment environment = prepareEnvironment(listeners, bootstrapContext, applicationArguments);
            // 配置 spring.beaninfo.ignore 
			configureIgnoreBeanInfo(environment);
            // 打印 banner,启动命令输出
			Banner printedBanner = printBanner(environment);
            // 创建context,注册了内置的BFPP和BPP
			context = createApplicationContext();
			context.setApplicationStartup(this.applicationStartup);
            // context预处理,把环境准备好,把启动类的类型注册到 BeanFactory中
			prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);
            // 调用refresh方法进行 spring容器操作,tomcat容器也是在里面进行创建的
			refreshContext(context);
            // 扩展方法
			afterRefresh(context, applicationArguments);
			Duration timeTakenToStartup = Duration.ofNanos(System.nanoTime() - startTime);
			if (this.logStartupInfo) {
				new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), timeTakenToStartup);
			}
            // 发布启动成功事件,可以进行业务监听
			listeners.started(context, timeTakenToStartup);
            // 调用 Runner接口实现的类型
			callRunners(context, applicationArguments);
		}
		catch (Throwable ex) {
			handleRunFailure(context, ex, listeners);
			throw new IllegalStateException(ex);
		}
		try {
			Duration timeTakenToReady = Duration.ofNanos(System.nanoTime() - startTime);
            // 发布ready事件
			listeners.ready(context, timeTakenToReady);
		}
		catch (Throwable ex) {
			handleRunFailure(context, ex, null);
			throw new IllegalStateException(ex);
		}
		return context;
	}

SpringApplication中的 createBootstrapContext方法

private DefaultBootstrapContext createBootstrapContext() {
   DefaultBootstrapContext bootstrapContext = new DefaultBootstrapContext();
   this.bootstrapRegistryInitializers.forEach((initializer) -> initializer.initialize(bootstrapContext));
   return bootstrapContext;
}

SpringApplication中的 prepareEnvironment方法

private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners,
      DefaultBootstrapContext bootstrapContext, ApplicationArguments applicationArguments) {
   // Create and configure the environment
   // 创建或者获取一个enviroment对象,需要判断不同web容器类型来创建不同类型的对象
   ConfigurableEnvironment environment = getOrCreateEnvironment();
   // 环境配置
   configureEnvironment(environment, applicationArguments.getSourceArgs());
    // 判断是否有 configurationProperties key的source,如果没有就添加一个 
   ConfigurationPropertySources.attach(environment);
    // 发布环境初始化时间
   listeners.environmentPrepared(bootstrapContext, environment);
    // 默认资源移动到最后 defaultProperties
   DefaultPropertiesPropertySource.moveToEnd(environment);
   Assert.state(!environment.containsProperty("spring.main.environment-prefix"),
         "Environment prefix cannot be set via properties.");
    // 把environment 绑定到 SpringApplication上
   bindToSpringApplication(environment);
   if (!this.isCustomEnvironment) {
      environment = convertEnvironment(environment);
   }
   ConfigurationPropertySources.attach(environment);
   return environment;
}
private ConfigurableEnvironment getOrCreateEnvironment() {
   if (this.environment != null) {
      return this.environment;
   }
   switch (this.webApplicationType) {
   case SERVLET:
      return new ApplicationServletEnvironment();
   case REACTIVE:
      return new ApplicationReactiveWebEnvironment();
   default:
      return new ApplicationEnvironment();
   }
}
	protected void configureEnvironment(ConfigurableEnvironment environment, String[] args) {
		if (this.addConversionService) {
			environment.setConversionService(new ApplicationConversionService());
		}
		configurePropertySources(environment, args);
		configureProfiles(environment, args);
	}

根据不同给的类型创建不同的上下问题对象,这里研究 SERVLET 容器

ApplicationContextFactory DEFAULT = (webApplicationType) -> {
   try {
      switch (webApplicationType) {
      case SERVLET:
         return new AnnotationConfigServletWebServerApplicationContext();
      case REACTIVE:
         return new AnnotationConfigReactiveWebServerApplicationContext();
      default:
         return new AnnotationConfigApplicationContext();
      }
   }
   catch (Exception ex) {
      throw new IllegalStateException("Unable create a default ApplicationContext instance, "
            + "you may need a custom ApplicationContextFactory", ex);
   }
};
	public AnnotationConfigServletWebServerApplicationContext() {
        // 里面进行了 environment的创建,和注册了一些内部类internalConfigurationAnnotationProcessor,用于在BFPP,和BPP场景下使用
        // AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry); 核心代码
		this.reader = new AnnotatedBeanDefinitionReader(this);
        
		this.scanner = new ClassPathBeanDefinitionScanner(this);
	}
private void prepareContext(DefaultBootstrapContext bootstrapContext, ConfigurableApplicationContext context,
			ConfigurableEnvironment environment, SpringApplicationRunListeners listeners,
			ApplicationArguments applicationArguments, Banner printedBanner) {
        // 覆盖环境变量
		context.setEnvironment(environment);
        // 配置一些context的属性
		postProcessApplicationContext(context);
       // 调用 ApplicationContextInitializer 的initialize继续进行初始化
		applyInitializers(context);
        // 发布事件
		listeners.contextPrepared(context);
        // 发送关闭 bootstrapContext的事件
		bootstrapContext.close(context);
		if (this.logStartupInfo) {
			logStartupInfo(context.getParent() == null);
			logStartupProfileInfo(context);
		}
		// Add boot specific singleton beans
    
   		// 添加一个特殊的Bean
		ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
		beanFactory.registerSingleton("springApplicationArguments", applicationArguments);
		if (printedBanner != null) {
			beanFactory.registerSingleton("springBootBanner", printedBanner);
		}
   		// 设置是否允许循环引用
		if (beanFactory instanceof AbstractAutowireCapableBeanFactory) {
			((AbstractAutowireCapableBeanFactory) beanFactory).setAllowCircularReferences(this.allowCircularReferences);
			if (beanFactory instanceof DefaultListableBeanFactory) {
				((DefaultListableBeanFactory) beanFactory)
						.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
			}
		}
    	
		if (this.lazyInitialization) {
			context.addBeanFactoryPostProcessor(new LazyInitializationBeanFactoryPostProcessor());
		}
		// Load the sources
		Set<Object> sources = getAllSources();
		Assert.notEmpty(sources, "Sources must not be empty");、
         // 它启动类传进来的类,注册到BeanFactory中
		load(context, sources.toArray(new Object[0]));
         // 发布事件
		listeners.contextLoaded(context);
	}