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)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • HTTP_POST请求的数据格式

    HTTP_POST请求的数据格式在HTTP的请求头中,可以使用Content-type来指定不同格式的请求信息。Content-type的类型常见的媒体格式类型:   text/html:HTML格式   text/plain:纯文本格式     &nbs…

    2022年4月1日
    30
  • ELK入门——ELK详细介绍(ELK概念和特点、Elasticsearch/Logstash/beats/kibana安装及使用介绍、插件介绍)

    ELK入门——ELK详细介绍(ELK概念和特点、Elasticsearch/Logstash/beats/kibana安装及使用介绍、插件介绍)主要参考链接ES内容大全(Elastic中国社区官方博客)ES视频教程(Elastic中国社区官方博客)Elastic相关软件和插件(官网)ES中文社区(讨论和提问)我的ELK专栏Linux操作(鸟哥的私房菜)Linux常用命令一、什么是ELK(端口9200)ELK学习总结——我们为什么要用ELK一般我们需要进行日志分析场景:直接在日志文件中grep、awk就可以获得自己想要的信息。但在规模较大的场景中,此方法效率低下,面临问题包括日志量太大如何归档、文本搜索太慢

    2025年7月23日
    3
  • 时间轮算法[通俗易懂]

    时间轮算法[通俗易懂]时间轮算法最近工作中使用了Xxl-Job框架来做分布式调度,内部采用了时间轮做整体调度,顺便学习并总结一下。概述绝对时间和相对时间定时任务一般有两种:1.约定一段时间后执行。2.约定某个时间点执行。​ 其实这两者是可以互相转换的,比如现在有一个定时任务是12点执行,当前时间是9点,那就可以认为这个任务是3小时后执行。同样,现在又有一个任务,是3小时后执行,那也可以认为这个任务12点执行。​ 假设我们现在有3个定时任务A、B、C,分别需要在3点、4点和9点执行,我们把

    2022年10月1日
    3
  • oracle的rac集群详解_Oracle rac

    oracle的rac集群详解_Oracle racORACLERAC数据库服务器上srvctl常用的一些操作命令,检查节点状态,检查VIP状态及配置等.作为笔记,以备不时之需.srvctl是ORACLERAC集群配置管理的工具,通过srvctl这个强大的工具来管理RAC,以下为对srvctl命令使用总结.检查节点应用程序状态[grid@db1~]$srvctlstatusnodeappsVIPdb1vipisenabl…

    2025年10月27日
    2
  • 安卓数据转移到iphone很慢_iphone数据迁移中断怎么继续

    安卓数据转移到iphone很慢_iphone数据迁移中断怎么继续如果你刚刚从安卓手机换了新的iPhone或者其他iOS设备,可以按照下面的步骤将数据转移到新设备,实现“无缝”过渡。准备工作在安卓手机上下载安装“转移到iOS”应用,打开安卓设备上的WiFi,并将新iOS设备和安卓设备都插入电源。转移需要在iPhone激活并设置新iOS设备过程进行,如果你已经激活,需要进入“设置”>“通用”>“还原”,然后选择“抹掉所有内容和设…

    2022年9月18日
    5
  • dotnet publish 不生成pdb文件

    dotnet publish 不生成pdb文件文章目录引言解决方案直接修改`.csproj`文件通过vs修改引言随着项目的体积越来越大,导致publish的时候文件越来越多,然而生产环境中其实pdb调试文件并没有什么作用(remotedebug)除外,所以也就灵机一动想着是否可以不生成呢?解决方案直接修改.csproj文件<PropertyGroupCondition=”‘$(Configuration)|$(Platform)’==’Release|AnyCPU'”><DebugType>none&lt

    2022年5月11日
    59

发表回复

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

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