springboot源码解析(一)

springboot源码解析(一)

1、springboot的入口程序

@SpringBootApplication
public class StartupApplication {
   

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

当程序开始执行之后,会调用SpringApplication的构造方法,进行某些初始参数的设置

//创建一个新的实例,这个应用程序的上下文将要从指定的来源加载Bean
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
   
    //资源初始化资源加载器,默认为null
	this.resourceLoader = resourceLoader;
    //断言主要加载资源类不能为 null,否则报错
	Assert.notNull(primarySources, "PrimarySources must not be null");
    //初始化主要加载资源类集合并去重
	this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
    //推断当前 WEB 应用类型,一共有三种:NONE,SERVLET,REACTIVE
	this.webApplicationType = WebApplicationType.deduceFromClasspath();
    //设置应用上线文初始化器,从"META-INF/spring.factories"读取ApplicationContextInitializer类的实例名称集合并去重,并进行set去重。(一共5个)
	setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
    //设置监听器,从"META-INF/spring.factories"读取ApplicationListener类的实例名称集合并去重,并进行set去重。(一共10个)
	setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
    //推断主入口应用类,通过当前调用栈,获取Main方法所在类,并赋值给mainApplicationClass
	this.mainApplicationClass = deduceMainApplicationClass();
	}

在上述构造方法中,有一个判断应用类型的方法,用来判断当前应用程序的类型:

	static WebApplicationType deduceFromClasspath() {
   
		if (ClassUtils.isPresent(WEBFLUX_INDICATOR_CLASS, null) && !ClassUtils.isPresent(WEBMVC_INDICATOR_CLASS, null)
				&& !ClassUtils.isPresent(JERSEY_INDICATOR_CLASS, null)) {
   
			return WebApplicationType.REACTIVE;
		}
		for (String className : SERVLET_INDICATOR_CLASSES) {
   
			if (!ClassUtils.isPresent(className, null)) {
   
				return WebApplicationType.NONE;
			}
		}
		return WebApplicationType.SERVLET;
	}
//WebApplicationType的类型
public enum WebApplicationType {
   

	/**
	 * The application should not run as a web application and should not start an
	 * embedded web server.
	 * 非web项目
	 */
	NONE,

	/**
	 * The application should run as a servlet-based web application and should start an
	 * embedded servlet web server.
	 * servlet web 项目
	 */
	SERVLET,

	/**
	 * The application should run as a reactive web application and should start an
	 * embedded reactive web server.
	 * 响应式 web 项目
	 */
	REACTIVE;

springboot启动的运行方法,可以看到主要是各种运行环境的准备工作

public ConfigurableApplicationContext run(String... args) {
   
    //1、创建并启动计时监控类
	StopWatch stopWatch = new StopWatch();
	stopWatch.start();
    //2、初始化应用上下文和异常报告集合
	ConfigurableApplicationContext context = null;
	Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
    //3、设置系统属性“java.awt.headless”的值,默认为true,用于运行headless服务器,进行简单的图像处理,多用于在缺少显示屏、键盘或者鼠标时的系统配置,很多监控工具如jconsole 需要将该值设置为true
	configureHeadlessProperty();
    //4、创建所有spring运行监听器并发布应用启动事件,简单说的话就是获取SpringApplicationRunListener类型的实例(EventPublishingRunListener对象),并封装进SpringApplicationRunListeners对象,然后返回这个SpringApplicationRunListeners对象。说的再简单点,getRunListeners就是准备好了运行时监听器EventPublishingRunListener。
	SpringApplicationRunListeners listeners = getRunListeners(args);
	listeners.starting();
	try {
   
        //5、初始化默认应用参数类
		ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
        //6、根据运行监听器和应用参数来准备spring环境
		ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);
        //将要忽略的bean的参数打开
		configureIgnoreBeanInfo(environment);
        //7、创建banner打印类
		Banner printedBanner = printBanner(environment);
        //8、创建应用上下文,可以理解为创建一个容器
		context = createApplicationContext();
        //9、准备异常报告器,用来支持报告关于启动的错误
		exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class,
					new Class[] {
    ConfigurableApplicationContext.class }, context);
        //10、准备应用上下文,该步骤包含一个非常关键的操作,将启动类注入容器,为后续开启自动化提供基础
		prepareContext(context, environment, listeners, applicationArguments, printedBanner);
        //11、刷新应用上下文
		refreshContext(context);
        //12、应用上下文刷新后置处理,做一些扩展功能
		afterRefresh(context, applicationArguments);
        //13、停止计时监控类
		stopWatch.stop();
        //14、输出日志记录执行主类名、时间信息
		if (this.logStartupInfo) {
   
				new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);
		}
        //15、发布应用上下文启动监听事件
		listeners.started(context);
        //16、执行所有的Runner运行器
		callRunners(context, applicationArguments);
	}catch (Throwable ex) {
   
		handleRunFailure(context, ex, exceptionReporters, listeners);
		throw new IllegalStateException(ex);
	}
	try {
   
        //17、发布应用上下文就绪事件
		listeners.running(context);
	}catch (Throwable ex) {
   
		handleRunFailure(context, ex, exceptionReporters, null);
		throw new IllegalStateException(ex);
	}
    //18、返回应用上下文
	return context;
}

下面详细介绍各个启动的环节:

1、创建并启动计时监控类,可以看到记录当前任务的名称,默认是空字符串,然后记录当前springboot应用启动的开始时间。

StopWatch stopWatch = new StopWatch();
stopWatch.start();
//详细源代码
public void start() throws IllegalStateException {
   
	start("");
}
public void start(String taskName) throws IllegalStateException {
   
	if (this.currentTaskName != null) {
   
		throw new IllegalStateException("Can't start StopWatch: it's already running");
	}
	this.currentTaskName = taskName;
	this.startTimeNanos = System.nanoTime();
}

2、初始化应用上下文和异常报告集合

ConfigurableApplicationContext context = null;
Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();

3、设置系统属性java.awt.headless的值:

/*
java.awt.headless模式是在缺少显示屏、键盘或者鼠标的系统配置
当配置了如下属性之后,应用程序可以执行如下操作:
	1、创建轻量级组件
	2、收集关于可用的字体、字体指标和字体设置的信息
	3、设置颜色来渲染准备图片
	4、创造和获取图像,为渲染准备图片
	5、使用java.awt.PrintJob,java.awt.print.*和javax.print.*类里的方法进行打印
*/
private void configureHeadlessProperty() {
   
		System.setProperty(SYSTEM_PROPERTY_JAVA_AWT_HEADLESS,
				System.getProperty(SYSTEM_PROPERTY_JAVA_AWT_HEADLESS, Boolean.toString(this.headless)));
}

4、创建所有spring运行监听器并发布应用启动事件

SpringApplicationRunListeners listeners = getRunListeners(args);
listeners.starting();

//创建spring监听器
private SpringApplicationRunListeners getRunListeners(String[] args) {
   
	Class<?>[] types = new Class<?>[] {
    SpringApplication.class, String[].class };
	return new SpringApplicationRunListeners(logger,
				getSpringFactoriesInstances(SpringApplicationRunListener.class, types, this
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Springboot源码解析PDF是一本深入解析Springboot框架的技术书籍,涵盖了Springboot的背景、原理、设计思路、运行机制、开发实践等方面。全书主要分为三部分:第一部分介绍Springboot的基础知识,包括Spring框架的常用注解、Springboot的配置、自动配置原理等;第二部分深入探讨Springboot的主要功能,如数据访问、Web开发、缓存、消息、安全等;第三部分着重介绍开发Springboot应用的最佳实践,包括Springboot与其他框架的结合使用、集成测试、监控与诊断等。 阅读Springboot源码解析PDF可以让开发者更深入理解Springboot的设计理念、技术实现以及应用场景,在实际项目开发中更加灵活、高效地使用Springboot。该书对于有一定Java和Spring框架基础的开发者来说是一本非常优秀的参考资料,也是Java开发者必不可少的技术读物。同时,该书也是借助源码解析的方式,让读者更加系统化地学习Springboot技术,具有很高的实用性和参考价值。总之,阅读Springboot源码解析PDF有助于开发者更好地掌握Springboot技术,提高应用开发效率和代码质量。 ### 回答2: Spring Boot源码解析pdf是一本介绍Spring Boot框架的开源书籍,该书的目的是帮助开发者深入了解Spring Boot的内部工作原理和实现细节。 该书首先从Spring Boot框架的源码结构和核心模块入手,详细介绍了Spring Boot的MVC、ORM、缓存、安全等核心功能的实现原理。同时,该书还介绍了Spring Boot对微服务的支持和整合Spring Cloud的方式,让开发者更深入了解Spring Boot在分布式架构中的应用。 在讲解源码实现原理的同时,该书还指出了一些常见的开发问题和易错点,并提供了相应的解决方案。此外,该书还通过一系列的案例,全面展示了Spring Boot的实际开发应用场景,帮助开发者更好地应用Spring Boot框架。 总的来说,Spring Boot源码解析pdf是一本非常实用的书籍,能够帮助开发者快速掌握Spring Boot框架的内部实现原理,提高开发效率和代码质量。同时,该书还可以作为学习Spring Boot的参考资料,对于想要深入学习和研究Spring Boot的开发者来说是非常有用的。 ### 回答3: Spring Boot 是一个很受欢迎的 Java 框架,它简化了开发者的工作,允许他们更快速地构建和部署应用程序。Spring Boot 的优点包括简洁的配置、内嵌的 Web 容器和现成的插件,让开发者可以更专注于业务逻辑。Spring Boot的源码解析是学习它的关键。 Spring Boot 的源码解析对Java初学者来说可能会比较复杂,但是它对于学习框架和原理是非常有益的。一个好的 Spring Boot 项目需要基于很好的基础,这就要求开发者了解其源码源码解析可以帮助开发者了解各种设计模式和组件的原理,有助于解决实际问题。 在 Spring Boot 的源码解析中,我们将会找到很多有用的信息。例如,我们可以看到 Spring Boot 如何通过注解处理器创建并配置 bean,这可以帮助我们更好地理解依赖注入和 IoC 容器。此外,我们还可以了解 Spring Boot 如何处理 HTTP 请求、创建模板、处理安全性等。这些知识可以帮助我们更好地理解 Spring Boot 内部的工作机制。 总之,Spring Boot 的源码解析是必不可少的一部分,它可以帮助开发者更好地了解和使用该框架,掌握在实践中所需的知识和技能。如果您是一名 Spring 开发者,那么深入了解 Spring Boot 的源码将会是一个很好的学习过程。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值