springboot启动流程

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);
	}
public SpringApplication(Class<?>... primarySources) {
		this(null, primarySources);
	}
public ConfigurableApplicationContext run(String... args) {
		/**
		 * 创建并且运行一个秒表总运行时间和每个命名任务的运行时间。
		 */
		StopWatch stopWatch = new StopWatch();
		stopWatch.start();
		ConfigurableApplicationContext context = null;
		Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
		configureHeadlessProperty();
		SpringApplicationRunListeners listeners = getRunListeners(args);
		//运行所有的监听器的starting
		listeners.starting();
		try {
			// 解析args 为SimpleCommandLinePropertySource并且保存args
			ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
			ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);
			configureIgnoreBeanInfo(environment);
			// 打印骚东西
			Banner printedBanner = printBanner(environment);
			// 根据webApplicationType 返回对应的ApplicationContext
			context = createApplicationContext();
			// 获取自定义报告列表  默认有FailureAnalysis
			exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class,
					new Class[] { ConfigurableApplicationContext.class }, context);
			prepareContext(context, environment, listeners, applicationArguments, printedBanner);
			refreshContext(context);
			afterRefresh(context, applicationArguments);
			// 停止stopWatch里面当前任务  计算总时间
			stopWatch.stop();
			// 打印springboot启动的时间和jvm
			if (this.logStartupInfo) {
				new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);
			}
			// 循环调用SpringApplicationRunListener.started
			listeners.started(context);
			// 执行所有的ApplicationRunner和CommandLineRunner
			callRunners(context, applicationArguments);
		}
		catch (Throwable ex) {
			handleRunFailure(context, ex, exceptionReporters, listeners);
			throw new IllegalStateException(ex);
		}

		try {
			// 执行所有SpringApplicationRunListener.running
			listeners.running(context);
		}
		catch (Throwable ex) {
			handleRunFailure(context, ex, exceptionReporters, null);
			throw new IllegalStateException(ex);
		}
		return context;
	}

1.configureHeadlessProperty()

/**
	 * 从系统变量获取java.awt.headless的值
	 * 如果没有就用当前的值
	 */
	private void configureHeadlessProperty() {
		System.setProperty(SYSTEM_PROPERTY_JAVA_AWT_HEADLESS,
				System.getProperty(SYSTEM_PROPERTY_JAVA_AWT_HEADLESS, Boolean.toString(this.headless)));
	}

2.getRunListeners(String[] args)

/**
	 * 获取spring工厂的所有实现了SpringApplicationRunListener的类
	 * 构建一个SpringApplicationRunListeners集合,储存了SpringApplication的log
	 * @param args
	 * @return
	 */
	private SpringApplicationRunListeners getRunListeners(String[] args) {
		Class<?>[] types = new Class<?>[] { SpringApplication.class, String[].class };
		return new SpringApplicationRunListeners(logger,
				getSpringFactoriesInstances(SpringApplicationRunListener.class, types, this, args));
	}
private <T> Collection<T> getSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, Object... args) {
		// 获取类加载器
		ClassLoader classLoader = getClassLoader();
		//使用名称并确保唯一以防止重复
		Set<String> names = new LinkedHashSet<>(SpringFactoriesLoader.loadFactoryNames(type, classLoader));
		// 创建spring工厂的实例对象
		List<T> instances = createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names);
		// 给实现了PriorityOrdered 的排序
		AnnotationAwareOrderComparator.sort(instances);
		return instances;
	}

3.prepareEnvironment(listeners, applicationArguments)

private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners,
			ApplicationArguments applicationArguments) {
		// 创建和配置环境
		ConfigurableEnvironment environment = getOrCreateEnvironment();
		configureEnvironment(environment, applicationArguments.getSourceArgs());
		ConfigurationPropertySources.attach(environment);
		// 循环执行listener的environmentPrepared方法
		listeners.environmentPrepared(environment);
		// 将环境绑定到{@link SpringApplication}。
		bindToSpringApplication(environment);
		//再判断下environment的类型
		if (!this.isCustomEnvironment) {
			environment = new EnvironmentConverter(getClassLoader()).convertEnvironmentIfNecessary(environment,
					deduceEnvironmentClass());
		}
		ConfigurationPropertySources.attach(environment);
		return environment;
	}
protected void configureEnvironment(ConfigurableEnvironment environment, String[] args) {
		if (this.addConversionService) {
			// 返回ApplicationConversionService的实例
			ConversionService conversionService = ApplicationConversionService.getSharedInstance();
			// 关联environment
			environment.setConversionService((ConfigurableConversionService) conversionService);
		}
		configurePropertySources(environment, args);
		// 更新environment里面的ActiveProfiles
		configureProfiles(environment, args);
	}
protected void configurePropertySources(ConfigurableEnvironment environment, String[] args) {
		MutablePropertySources sources = environment.getPropertySources();
		// 如果默认的Properties不为null和空 就添加到sources末尾
		if (this.defaultProperties != null && !this.defaultProperties.isEmpty()) {
			sources.addLast(new MapPropertySource("defaultProperties", this.defaultProperties));
		}
		// 是否添加命令行的参数配置
		if (this.addCommandLineProperties && args.length > 0) {
			String name = CommandLinePropertySource.COMMAND_LINE_PROPERTY_SOURCE_NAME;
			/**
			 * 判断里面是否已经有commandLineArgs
			 * 用给定的属性源对象用给定的名称替换属性源。
			 */
			if (sources.contains(name)) {
				PropertySource<?> source = sources.get(name);
				CompositePropertySource composite = new CompositePropertySource(name);
				composite.addPropertySource(
						new SimpleCommandLinePropertySource("springApplicationCommandLineArgs", args));
				composite.addPropertySource(source);
				sources.replace(name, composite);
			}
			else {
				// 将commandLineArgs添加到第一个
				sources.addFirst(new SimpleCommandLinePropertySource(args));
			}
		}
	}
protected void configureProfiles(ConfigurableEnvironment environment, String[] args) {
		Set<String> profiles = new LinkedHashSet<>(this.additionalProfiles);
		profiles.addAll(Arrays.asList(environment.getActiveProfiles()));
		environment.setActiveProfiles(StringUtils.toStringArray(profiles));
	}
public static void attach(Environment environment) {
		// 判断environment是否为ConfigurableEnvironment的实例对象 不是就抛出异常
		Assert.isInstanceOf(ConfigurableEnvironment.class, environment);
		MutablePropertySources sources = ((ConfigurableEnvironment) environment).getPropertySources();
		// 获取configurationProperties
		PropertySource<?> attached = sources.get(ATTACHED_PROPERTY_SOURCE_NAME);
		//
		/**
		 * 如果attached不为null 并且和sources里面的不一样 就删除重新添加到sources的头上面
		 * 为null的话就直接添加到sources头上面
		 */
		if (attached != null && attached.getSource() != sources) {
			sources.remove(ATTACHED_PROPERTY_SOURCE_NAME);
			attached = null;
		}
		if (attached == null) {
			sources.addFirst(new ConfigurationPropertySourcesPropertySource(ATTACHED_PROPERTY_SOURCE_NAME,
					new SpringConfigurationPropertySources(sources)));
		}
	}
/**
	 * 将环境绑定到{@link SpringApplication}。
	 * @param environment the environment to bind
	 */
	protected void bindToSpringApplication(ConfigurableEnvironment environment) {
		try {
			Binder.get(environment).bind("spring.main", Bindable.ofInstance(this));
		}
		catch (Exception ex) {
			throw new IllegalStateException("Cannot bind to SpringApplication", ex);
		}
	}

4.configureIgnoreBeanInfo(environment)

private void configureIgnoreBeanInfo(ConfigurableEnvironment environment) {
		/**
		 * 判断系统环境是否有spring.beaninfo.ignore的值
		 * 没有的话从environment里面获取,如果environment里面为null 就返回true
		 */
		if (System.getProperty(CachedIntrospectionResults.IGNORE_BEANINFO_PROPERTY_NAME) == null) {
			Boolean ignore = environment.getProperty("spring.beaninfo.ignore", Boolean.class, Boolean.TRUE);
			System.setProperty(CachedIntrospectionResults.IGNORE_BEANINFO_PROPERTY_NAME, ignore.toString());
		}
	}

5.printBanner(environment)

private Banner getBanner(Environment environment) {
		Banners banners = new Banners();
		/**
		 * 判断是否有banner."gif", "jpg", "png"其中的一个
		 * 有就构建ImageBanner添加到banners里面
		 */
		banners.addIfNotNull(getImageBanner(environment));
		/**
		 * 判断是否有banner.txt
		 * 有就构建ResourceBanner添加到banners里面
		 */
		banners.addIfNotNull(getTextBanner(environment));
		// 判断banners不为空就直接返回
		if (banners.hasAtLeastOneBanner()) {
			return banners;
		}
		// 如果设置了错误回调Banner就返回
		if (this.fallbackBanner != null) {
			return this.fallbackBanner;
		}
		//返回默认的SpringBootBanner
		return DEFAULT_BANNER;
	}

6.createApplicationContext()

/**
	 * 用于创建{@link ApplicationContext}的策略方法。
	 * 默认情况下,此方法将使用任何明确设置的应用程序上下文或应用程序上下文类,然后再降为合适的默认值。
	 * @return the application context (not yet refreshed)
	 * @see #setApplicationContextClass(Class)
	 */
	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);
	}

7.getSpringFactoriesInstances(SpringBootExceptionReporter.class,
new Class[] { ConfigurableApplicationContext.class }, context)

private <T> Collection<T> getSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, Object... args) {
		// 获取类加载器
		ClassLoader classLoader = getClassLoader();
		//使用名称并确保唯一以防止重复
		Set<String> names = new LinkedHashSet<>(SpringFactoriesLoader.loadFactoryNames(type, classLoader));
		// 创建spring工厂的实例对象
		List<T> instances = createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names);
		// 给实现了PriorityOrdered 的排序
		AnnotationAwareOrderComparator.sort(instances);
		return instances;
	}

8.prepareContext(context, environment, listeners, applicationArguments, printedBanner)

private void prepareContext(ConfigurableApplicationContext context, ConfigurableEnvironment environment,
			SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments, Banner printedBanner) {
		/**
		 *
		 * 将environment委托给基础的 {@link AnnotatedBeanDefinitionReader}{@link ClassPathBeanDefinitionScanner}成员。
		 * 和AbstractApplicationContext成员。
		 */
		context.setEnvironment(environment);
		postProcessApplicationContext(context);
		// 循环调用ApplicationContextInitializer.initialize
		applyInitializers(context);
		// 循环调用监听器的SpringApplicationRunListener.contextPrepared
		listeners.contextPrepared(context);
		if (this.logStartupInfo) {
			// 打印 info和debug级别日志 包含pid ApplicationName context等等
			logStartupInfo(context.getParent() == null);
			// 打印 info级别日志 对activeProfiles和defaultProfiles的记录
			logStartupProfileInfo(context);
		}
		// 添加引导特别的单例bean
		ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
		beanFactory.registerSingleton("springApplicationArguments", applicationArguments);
		if (printedBanner != null) {
			beanFactory.registerSingleton("springBootBanner", printedBanner);
		}
		if (beanFactory instanceof DefaultListableBeanFactory) {
			// 设置是否允许重新注册覆盖相同名称的Bean
			((DefaultListableBeanFactory) beanFactory)
					.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
		}
		/**
		 * 是否懒加载是的话就添加Bean工厂后置处理器 LazyInitializationBeanFactoryPostProcessor
		 */
		if (this.lazyInitialization) {
			context.addBeanFactoryPostProcessor(new LazyInitializationBeanFactoryPostProcessor());
		}
		// 返回primarySources和sources的不可变set集合
		Set<Object> sources = getAllSources();
		Assert.notEmpty(sources, "Sources must not be empty");
		// registerBeanDefinition逻辑
		load(context, sources.toArray(new Object[0]));
		// 循环执行SpringApplicationRunListener.contextLoaded
		listeners.contextLoaded(context);
	}
protected void load(ApplicationContext context, Object[] sources) {
		if (logger.isDebugEnabled()) {
			logger.debug("Loading source " + StringUtils.arrayToCommaDelimitedString(sources));
		}
		//构建一个包括XML和JavaConfig)加载bean定义loader
		BeanDefinitionLoader loader = createBeanDefinitionLoader(getBeanDefinitionRegistry(context), sources);
		// 关联Bean名称 命名策略
		if (this.beanNameGenerator != null) {
			loader.setBeanNameGenerator(this.beanNameGenerator);
		}
		// 关联资源
		if (this.resourceLoader != null) {
			loader.setResourceLoader(this.resourceLoader);
		}
		// 关联环境
		if (this.environment != null) {
			loader.setEnvironment(this.environment);
		}
		loader.load();
	}
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);
		}
		if (isEligible(source)) {
			//注册BeanDefinition的实现
			this.annotatedReader.register(source);
			return 1;
		}
		return 0;
	}

9.refreshContext(context)

private void refreshContext(ConfigurableApplicationContext context) {
		// 是否注册关闭的钩子 看过tomcat源码的这里就比较熟悉了
		if (this.registerShutdownHook) {
			try {
				context.registerShutdownHook();
			}
			catch (AccessControlException ex) {
				// 在某些环境中不允许使用。
			}
		}
		refresh((ApplicationContext) context);
	}
/**
	 * 刷新基础的{@link ApplicationContext}。
	 * @param applicationContext the application context to refresh
	 */
	protected void refresh(ConfigurableApplicationContext applicationContext) {
		applicationContext.refresh();
	}
public final void refresh() throws BeansException, IllegalStateException {
		try {
			/**
			 * AbstractApplicationContext.refresh() 逻辑
			 * 主要看子类实现onRefresh()
			 */
			super.refresh();
		}
		catch (RuntimeException ex) {
			WebServer webServer = this.webServer;
			if (webServer != null) {
				webServer.stop();
			}
			throw ex;
		}
	}
protected void onRefresh() {
		//  初始化GenericWebApplicationContext主题功能
		super.onRefresh();
		try {
			createWebServer();
		}
		catch (Throwable ex) {
			throw new ApplicationContextException("Unable to start web server", ex);
		}
	}

createWebServer()创建内置Web容器

private void createWebServer() {
		WebServer webServer = this.webServer;
		ServletContext servletContext = getServletContext();
		if (webServer == null && servletContext == null) {
			ServletWebServerFactory factory = getWebServerFactory();
			this.webServer = factory.getWebServer(getSelfInitializer());
			getBeanFactory().registerSingleton("webServerGracefulShutdown",
					new WebServerGracefulShutdownLifecycle(this.webServer));
			// 通过spring的生命中期联动Web容器的启动和停止
			getBeanFactory().registerSingleton("webServerStartStop",
					new WebServerStartStopLifecycle(this, this.webServer));
		}
		else if (servletContext != null) {
			try {
				getSelfInitializer().onStartup(servletContext);
			}
			catch (ServletException ex) {
				throw new ApplicationContextException("Cannot initialize servlet context", ex);
			}
		}
		initPropertySources();
	}
/**
	 *返回用于创建嵌入式{@link WebServer}的{@link ServletWebServerFactory}。
	 * 默认情况下,此方法在上下文本身中搜索合适的bean。
	 * @return a {@link ServletWebServerFactory} (never {@code null})
	 */
	protected ServletWebServerFactory getWebServerFactory() {
		/**
		 * 使用Bean名称,这样我们就不会考虑层次结构
		 * 做了校验不能为0也不能大于1
		 */
		String[] beanNames = getBeanFactory().getBeanNamesForType(ServletWebServerFactory.class);
		if (beanNames.length == 0) {
			throw new ApplicationContextException("Unable to start ServletWebServerApplicationContext due to missing "
					+ "ServletWebServerFactory bean.");
		}
		if (beanNames.length > 1) {
			throw new ApplicationContextException("Unable to start ServletWebServerApplicationContext due to multiple "
					+ "ServletWebServerFactory beans : " + StringUtils.arrayToCommaDelimitedString(beanNames));
		}
		return getBeanFactory().getBean(beanNames[0], ServletWebServerFactory.class);
	}

WebServerStartStopLifecycle负责Web容器的启动和停止

/**
 * {@link SmartLifecycle},以在{@link ServletWebServerApplicationContext}中启动和停止{@link WebServer}。
 *
 * @author Andy Wilkinson
 */
class WebServerStartStopLifecycle implements SmartLifecycle {

	private final ServletWebServerApplicationContext applicationContext;

	private final WebServer webServer;

	private volatile boolean running;

	WebServerStartStopLifecycle(ServletWebServerApplicationContext applicationContext, WebServer webServer) {
		this.applicationContext = applicationContext;
		this.webServer = webServer;
	}

	@Override
	public void start() {
		this.webServer.start();
		this.running = true;
		this.applicationContext
				.publishEvent(new ServletWebServerInitializedEvent(this.webServer, this.applicationContext));
	}

	@Override
	public void stop() {
		this.webServer.stop();
	}

	@Override
	public boolean isRunning() {
		return this.running;
	}

	@Override
	public int getPhase() {
		return Integer.MAX_VALUE - 1;
	}

}
public void start() throws WebServerException {
		synchronized (this.monitor) {
			if (this.started) {
				return;
			}
			try {
				//启动关联服务的连接器
				addPreviouslyRemovedConnectors();
				Connector connector = this.tomcat.getConnector();
				if (connector != null && this.autoStart) {
					performDeferredLoadOnStartup();
				}
				checkThatConnectorsHaveStarted();
				this.started = true;
				logger.info("Tomcat started on port(s): " + getPortsDescription(true) + " with context path '"
						+ getContextPath() + "'");
			}
			catch (ConnectorStartFailedException ex) {
				stopSilently();
				throw ex;
			}
			catch (Exception ex) {
				PortInUseException.throwIfPortBindingException(ex, () -> this.tomcat.getConnector().getPort());
				throw new WebServerException("Unable to start embedded Tomcat server", ex);
			}
			finally {
				Context context = findContext();
				ContextBindings.unbindClassLoader(context, context.getNamingToken(), getClass().getClassLoader());
			}
		}
	}

10.afterRefresh(context, applicationArguments)

/**
	 * 在刷新上下文后调用。
	 * @param context the application context
	 * @param args the application arguments
	 */
	protected void afterRefresh(ConfigurableApplicationContext context, ApplicationArguments args) {
	}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值