首先上一张图, 图片来自 SpringBoot 启动流程解析 https://www.cnblogs.com/trgl/p/7353782.html
本文基于 spring-boot-2.0.4.RELEASE.jar 包分析.
程序启动入口
- public static void main(String[] args) {
- SpringApplication.run(Springboot2Application.class, args);
- }
run 是一个静态方法, 最后会调用创建 SpringApplication 实例并 run
- 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);
- }
我们先看 new SpringApplication(xx) 构建的实例.
- public SpringApplication(Class... primarySources) {
- this((ResourceLoader)null, primarySources);
- }
- public SpringApplication(ResourceLoader resourceLoader, Class... primarySources) {
- this.sources = new LinkedHashSet();
- this.bannerMode = Mode.CONSOLE;
- this.logStartupInfo = true;
- this.addCommandLineProperties = true;
- this.headless = true;
- this.registerShutdownHook = true;
- this.additionalProfiles = new HashSet();
- this.resourceLoader = resourceLoader;
- Assert.notNull(primarySources, "PrimarySources must not be null");
- // 配置 source
- this.primarySources = new LinkedHashSet(Arrays.asList(primarySources));
- // 判断是否 web 应用
- this.webApplicationType = this.deduceWebApplicationType();
- // 创建初始化构造器
- this.setInitializers(this.getSpringFactoriesInstances(ApplicationContextInitializer.class));
- // 创建应用监听器
- this.setListeners(this.getSpringFactoriesInstances(ApplicationListener.class));
- // 推断出 main 方法类
- this.mainApplicationClass = this.deduceMainApplicationClass();
- }
SpringApplication 的构造函数主要设置了一些基本参数并配置 source, 判断了是否 Web 应用, 创建初始化构造器, 创建应用监听器, 找出 main 方法所在的类.
getSpringFactoriesInstances 为获取 spring 工厂中的实例, 具体代码块为
- private <T> Collection<T> getSpringFactoriesInstances(Class<T> type) {
- return this.getSpringFactoriesInstances(type, new Class[0]);
- }
- private <T> Collection<T> getSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, Object... args) {
- // 获取类加载器
- ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
- // 通过类加载器, 获取指定的 spring.factories 文件, 并获取文件中工厂类的全路径名
- Set<String> names = new LinkedHashSet(SpringFactoriesLoader.loadFactoryNames(type, classLoader));
- // 通过类路径反射得到工厂 class 对象, 构造方法
- List<T> instances = this.createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names);
- AnnotationAwareOrderComparator.sort(instances);
- return instances;
- }
new SpringApplication(xx) 构建完实例后, 会进行 run 方法.
- public ConfigurableApplicationContext run(String... args) {
- StopWatch stopWatch = new StopWatch();
- // 应用启动计时器开始计时
- stopWatch.start();
- ConfigurableApplicationContext context = null;
- Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
- //Headless 模式配置
- configureHeadlessProperty();
- // 获取启动监听器
- SpringApplicationRunListeners listeners = getRunListeners(args);
- // 应用启动监听器开始计时
- listeners.starting();
- try {
- ApplicationArguments applicationArguments = new DefaultApplicationArguments(
- args);
- // 配置环境模块 (祥见下面 prepareEnvironment 方法)
- ConfigurableEnvironment environment = prepareEnvironment(listeners,
- applicationArguments);
- // 配置需要忽略的 bean
- configureIgnoreBeanInfo(environment);
- //Banner 配置
- Banner printedBanner = printBanner(environment);
- // 创建应用上下文对象
- context = createApplicationContext();
- exceptionReporters = getSpringFactoriesInstances(
- SpringBootExceptionReporter.class,
- new Class[] { ConfigurableApplicationContext.class }, context);
- // 上下文基本属性配置 (祥见下面 prepareContext 方法)
- prepareContext(context, environment, listeners, applicationArguments,
- printedBanner);
- // 更新应用上下文 (祥见下面 refresh 方法)
- 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;
- }
- private ConfigurableEnvironment prepareEnvironment(
- SpringApplicationRunListeners listeners,
- ApplicationArguments applicationArguments) {
- // 创建配置环境
- ConfigurableEnvironment environment = getOrCreateEnvironment();
- // 加载属性文件
- configureEnvironment(environment, applicationArguments.getSourceArgs());
- // 监听器监听配置
- listeners.environmentPrepared(environment);
- bindToSpringApplication(environment);
- if (this.webApplicationType == WebApplicationType.NONE) {
- environment = new EnvironmentConverter(getClassLoader())
- .convertToStandardEnvironmentIfNecessary(environment);
- }
- ConfigurationPropertySources.attach(environment);
- return environment;
- }
- private void prepareContext(ConfigurableApplicationContext context,
- ConfigurableEnvironment environment, SpringApplicationRunListeners listeners,
- ApplicationArguments applicationArguments, Banner printedBanner) {
- // 加载配置环境
- context.setEnvironment(environment);
- //ResourceLoader 资源加载器
- postProcessApplicationContext(context);
- // 初始化环境
- applyInitializers(context);
- // 配置监听
- listeners.contextPrepared(context);
- if (this.logStartupInfo) {
- logStartupInfo(context.getParent() == null);
- logStartupProfileInfo(context);
- }
- // Add boot specific singleton beans
- context.getBeanFactory().registerSingleton("springApplicationArguments",
- applicationArguments);
- if (printedBanner != null) {
- context.getBeanFactory().registerSingleton("springBootBanner", printedBanner);
- }
- // Load the sources
- Set<Object> sources = getAllSources();
- Assert.notEmpty(sources, "Sources must not be empty");
- // 加载启动参数
- load(context, sources.toArray(new Object[0]));
- // 监听加载应用上下文
- listeners.contextLoaded(context);
- }
- public void refresh() throws BeansException, IllegalStateException {
- Object var1 = this.startupShutdownMonitor;
- synchronized(this.startupShutdownMonitor) {
- // 准备更新上下文时的预备工作: 1. 初始化 PropertySource; 2. 验证 Enrivonment 中必要的属性
- this.prepareRefresh();
- // 获取上下文中的 BeanFactory
- ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();
- // 对 BeanFactory 做些预备工作
- this.prepareBeanFactory(beanFactory);
- try {
- // 对 BeanFactory 进行预处理
- this.postProcessBeanFactory(beanFactory);
- // 执行容器中的 BeanFactoryPostProcessor
- this.invokeBeanFactoryPostProcessors(beanFactory);
- // 注册 BeanPostProcessor
- this.registerBeanPostProcessors(beanFactory);
- // 初始化 MessageSource(国际化相关)
- this.initMessageSource();
- // 初始化容器事件广播器 (用来发布事件)
- this.initApplicationEventMulticaster();
- // 初始化一些特殊的 Bean, 主要做了: 1. 初始化 ThemeSource(跟国际化相关的接口) 2. 创建 WebServer
- this.onRefresh();
- // 将所有监听器注册到前两步创建的事件广播器中
- this.registerListeners();
- // 结束 BeanFactory 的初始化工作 (这一步主要用来将所有的单例 BeanDefinition 实例化)
- this.finishBeanFactoryInitialization(beanFactory);
- // 上下文刷新完毕
- this.finishRefresh();
- } catch (BeansException var9) {
- if (this.logger.isWarnEnabled()) {
- this.logger.warn("Exception encountered during context initialization - cancelling refresh attempt:" + var9);
- }
- this.destroyBeans();
- this.cancelRefresh(var9);
- throw var9;
- } finally {
- this.resetCommonCaches();
- }
- }
- }
来源: http://www.bubuko.com/infodetail-3340099.html