SpringBoot源码学习(更新中)

SpringBoot源码学习(更新中)SpringBoot源码学习(更新中)

大家好,又见面了,我是你们的朋友全栈君。

最近在项目中运用了Springboot,简单的学习了简单的使用,于是想去看看源码是如何实现的。

自己也是第一次尝试看源码,结合了网上的东西和自己的理解,在博客里写点东西,做做积累, 如果其中哪些地方解释有问题,

欢迎老司机指出

参考文章:

1.https://my.oschina.net/u/3081965/blog/916126

2.http://www.cfanz.cn/index.php?c=article&a=read&id=307782

首先不知道从哪里入手,于是我从项目的启动入口开始。

以下就是项目入口代码,很简单,由于是在慕课网上学习的,这里的报名就直接写imooc了(这个为对应springboot的学习地址:http://www.imooc.com/learn/767)

这边的spring-boot版本为1.4.7

package com.imooc;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class GirlApplication {

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

@SpringBootApplication 注解暂时不讲,先从下面这个方法开始讲起
SpringApplication.run(GirlApplication.class, args);

点击进去可以看到

	/**
	 * Static helper that can be used to run a {@link SpringApplication} from the
	 * specified source using default settings.
	 * @param source the source to load
	 * @param args the application arguments (usually passed from a Java main method)
	 * @return the running {@link ApplicationContext}
	 */
	public static ConfigurableApplicationContext run(Object source, String... args) {
   
   
 //第一次进入到达这里
		return run(new Object[] { source }, args);
	}

	/**
	 * Static helper that can be used to run a {@link SpringApplication} from the
	 * specified sources using default settings and user supplied arguments.
	 * @param sources the sources to load
	 * @param args the application arguments (usually passed from a Java main method)
	 * @return the running {@link ApplicationContext}
	 */
	public static ConfigurableApplicationContext run(Object[] sources, String[] args) {
   
   
 //上面方法后进入这里
		return new SpringApplication(sources).run(args);
	}

首先为第一步,第一步调用第二部的方法,这里主要看下第二步。

第二步这边分为两个步骤去看,第一个步骤为调用SpringApplication类的构造方法创建对象,第二步为调用创建对象的run方法,这里以这两个步骤进行解读。

构建对象:
	/**
	 * Create a new {@link SpringApplication} instance. The application context will load
	 * beans from the specified sources (see {@link SpringApplication class-level}
	 * documentation for details. The instance can be customized before calling
	 * {@link #run(String...)}.
	 * @param sources the bean sources
	 * @see #run(Object, String[])
	 * @see #SpringApplication(ResourceLoader, Object...)
	 */
	public SpringApplication(Object... sources) {
   
   
 //调用初始化方法
		initialize(sources);
	}

	@SuppressWarnings({ "unchecked", "rawtypes" })
	private void initialize(Object[] sources) {
   
   
 //将对象资源存放到sources这个linkedSet下,这里的sources就是上诉的com.imooc.GirlController对象
		if (sources != null && sources.length > 0) {
			this.sources.addAll(Arrays.asList(sources));
		}
 //这里暂时没有看懂,从字面上来看,是判断是否有web环境
		this.webEnvironment = deduceWebEnvironment();
 //实例化Initializer,initializers成员变量,是一个ApplicationContextInitializer类型对象的集合。 
 //顾名思义,ApplicationContextInitializer是一个可以用来初始化ApplicationContext的接口。
 //初始化ApplicationContext的Initializer程序
 //boot包下的META-INF/spring.factories
 0 = "org.springframework.boot.context.ConfigurationWarningsApplicationContextInitializer"
 1 = "org.springframework.boot.context.ContextIdApplicationContextInitializer"
 2 = "org.springframework.boot.context.config.DelegatingApplicationContextInitializer"
 3 = "org.springframework.boot.context.web.ServerPortInfoApplicationContextInitializer"
 //autoconfigure下的META-INF/spring.factories
 4 = "org.springframework.boot.autoconfigure.SharedMetadataReaderFactoryContextInitializer"
 5 = "org.springframework.boot.autoconfigure.logging.AutoConfigurationReportLoggingInitializer"
		setInitializers((Collection) getSpringFactoriesInstances(
				ApplicationContextInitializer.class));
 //实例化监听器
 //初始化 ApplicationListener  boot下9个,autoconfigure一个
 //0 = "org.springframework.boot.ClearCachesApplicationListener"
 //1 = "org.springframework.boot.builder.ParentContextCloserApplicationListener"

//2 = "org.springframework.boot.context.FileEncodingApplicationListener"
//3 = "org.springframework.boot.context.config.AnsiOutputApplicationListener"
//4 = "org.springframework.boot.context.config.ConfigFileApplicationListener"
//5 = "org.springframework.boot.context.config.DelegatingApplicationListener"
//6 = "org.springframework.boot.liquibase.LiquibaseServiceLocatorApplicationListener"
//7 = "org.springframework.boot.logging.ClasspathLoggingApplicationListener"
//8 = "org.springframework.boot.logging.LoggingApplicationListener"
//9 = "org.springframework.boot.autoconfigure.BackgroundPreinitializer"setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));

 //找出main方法的全类名并返回其实例并设置到SpringApplication的this.mainApplicationClass完成初始化
		this.mainApplicationClass = deduceMainApplicationClass();
	}

这里附上deduceWebEnvironment()方法的实现,其中WEB_ENVIRONMENT_CLASSES的值为


 private static final String[] WEB_ENVIRONMENT_CLASSES = { "javax.servlet.Servlet",
			"org.springframework.web.context.ConfigurableWebApplicationContext" };

 private boolean deduceWebEnvironment() {
		for (String className : WEB_ENVIRONMENT_CLASSES) {
			if (!ClassUtils.isPresent(className, null)) {
				return false;
			}
		}
		return true;
	}
上面SpringApplication的初始化动作已经做完了,然后看下run方法里做了哪些操作。
public ConfigurableApplicationContext run(String... args) {
   
   
   
 //StopWatch是一个监视器,主要是用来记录程序的运行时间,这里是用来记录程序启动所需要的时间
   StopWatch stopWatch = new StopWatch();
   stopWatch.start();
   ConfigurableApplicationContext context = null;
   FailureAnalyzers analyzers = null;
   configureHeadlessProperty();
   SpringApplicationRunListeners listeners = getRunListeners(args);
   listeners.started();
   try {
      ApplicationArguments applicationArguments = new DefaultApplicationArguments(
            args);
      ConfigurableEnvironment environment = prepareEnvironment(listeners,
            applicationArguments);
      Banner printedBanner = printBanner(environment);
      context = createApplicationContext();
      analyzers = new FailureAnalyzers(context);
      prepareContext(context, environment, listeners, applicationArguments,
            printedBanner);
      refreshContext(context);
      afterRefresh(context, applicationArguments);
      listeners.finished(context, null);
      stopWatch.stop();
      if (this.logStartupInfo) {
         new StartupInfoLogger(this.mainApplicationClass)
               .logStarted(getApplicationLog(), stopWatch);
      }
      return context;
   }
   catch (Throwable ex) {
      handleRunFailure(context, listeners, analyzers, ex);
      throw new IllegalStateException(ex);
   }
}



版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/132201.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 决策引擎选购指南[通俗易懂]

    决策引擎选购指南[通俗易懂]决策引擎选购指南决策引擎或规则引擎的概念在2015年随着互联网金融行业的发展得到了快速普及,逐渐被各大公司接纳并入到企业基础设施中,用于集中管理高频多变的业务运营策略,相对于原先的硬代码维护的方式,有着便捷、高效、低成本的特点。市面上关于决策引擎的分享不少,但主要集中在技术层面的经验分享,比如如何从0到1搭建一套决策引擎,大家如果感兴趣也可以自行进行查阅。反而从公司层面出发,如何评估以及选择决策引擎的文章十分有限,从而导致了公司在采购的时候往往因为信息不对称而十分被动。因此,本文将从一位…

    2022年6月24日
    31
  • 第四章:redis 数组结构的set和一些通用命令「建议收藏」

    第四章:redis 数组结构的set和一些通用命令「建议收藏」第四章:redis 数组结构的set和一些通用命令

    2022年4月23日
    48
  • tidb数据库隔离级别剖析

    tidb数据库隔离级别剖析本文章来源于:https://github.com/Zeb-D/my-review,请star强力支持,你的支持,就是我的动力。[TOC]前言在线应用业务中,数据库是一个非常重要的组成部分,特别是现在的微服务架构为了获得水平扩展能力,我们倾向于将状态都存储在数据库中,这要求数据库能够正确、高性能处理请求,但这是一个几乎不可能达到的要求,所以数据库的设计者们定义了隔离级别这一个概念,在高…

    2022年5月25日
    38
  • C语言 文件读写的实现

    C语言 文件读写的实现关于C语言的文件读写,我将介绍下面这几种方式:字符的读写:使用fgetc()函数和fputc()函数;字符串的读写:使用fgets()函数和fputs()函数;格式化的读写(主要用于文本文件):使用fscanf()函数和fprintf()函数。字符读写:1.fputc()函数fputc(c,fp);//用于将一个字符写入文件其中,…

    2022年5月5日
    46
  • size_t和int区别

    size_t和int区别size_t和intsize_t是一些C/C++标准在stddef.h中定义的。这个类型足以用来表示对象的大小。size_t的真实类型与操作系统有关。在32位架构中被普遍定义为:typedefunsignedintsize_t;而在64位架构中被定义为:typedefunsignedlongsize_t;size_t在32位架构上…

    2022年6月6日
    97
  • phpstorm2021永久激活码【2021最新】

    (phpstorm2021永久激活码)最近有小伙伴私信我,问我这边有没有免费的intellijIdea的激活码,然后我将全栈君台教程分享给他了。激活成功之后他一直表示感谢,哈哈~https://javaforall.net/100143.htmlIntelliJ2021最新激活注册码,破解教程可免费永久激活,亲测有效,上面是详细链接哦~S32P…

    2022年3月26日
    296

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号