IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> Spring Boot 启动源码解析二 -> 正文阅读

[Java知识库]Spring Boot 启动源码解析二

Spring Boot 使用及启动源码解析一_踩踩踩从踩的博客-CSDN博客

前言

之前的文章主要介绍的是spring boot? ?也就是 spring boot application? 这个启动类, 有兴趣的可以看看之前的,这篇文章继续?研究? spring boot 自动装配,如何利用自动装配 将所有的对象 注入的容器中,方便我们使用,对于我们开发新组件,很有用,有时候 自己的开发时,也许你应该会想,我都没加什么@component? 注解,当然更没有加 @configuration + @bean 的方式注入,但为什么我们就能注入进来拉,像mysql 等? 中间组件,其实也不是难事,看一下源码 就明白了。

自动装配注解

?我们使用的时候 有 SpringBootApplication 注解? 继承自? ?EnableAutoConfiguration? 还有? componentScan 等注解?

后面? 进去 很简单的 autoConfigurationPackage? ? 有? 自动配置 配置??

?这里在引入到? register .class 类? ? 注册器

在selector 选择器 才是最重要 会 一堆stater 在这里选择? 到底要加载 那个 类进行加载的。

?引入那个类进行加载

?找到对应的 autoconfiguration 类,我们选择 自动装配的类

说一下怎么加载到 selecter? 并加载 对应的autoconfigruation? ?去怎么加载? 到 配置文件反射到的对象。

读取spring .factory? 文件 并且扫描 并配置 具体对象的注入。 具体可以看看这篇文章。

Spring boot基本使用及 stater机制原理_踩踩踩从踩的博客-CSDN博客_spring stater

springboot中监听器

spring boot 的源码中,会发现内部大量的监听器,这些监听器大概有两类。

# Run Listeners
#事件发布运行监听器,是springboot中配置的唯一一个应用运行监听器,作用是通过一个多路广播器,将springboot运行状态的变化,构建成事件,并广播给各个监听器
org.springframework.boot.SpringApplicationRunListener=\
org.springframework.boot.context.event.EventPublishingRunListener

# Application Listeners
org.springframework.context.ApplicationListener=\
org.springframework.boot.ClearCachesApplicationListener(),\
org.springframework.boot.builder.ParentContextCloserApplicationListener,\
org.springframework.boot.cloud.CloudFoundryVcapEnvironmentPostProcessor,\
org.springframework.boot.context.FileEncodingApplicationListener,\
org.springframework.boot.context.config.AnsiOutputApplicationListener,\
org.springframework.boot.context.config.ConfigFileApplicationListener,\
org.springframework.boot.context.config.DelegatingApplicationListener,\
org.springframework.boot.context.logging.ClasspathLoggingApplicationListener,\
org.springframework.boot.context.logging.LoggingApplicationListener,\
org.springframework.boot.liquibase.LiquibaseServiceLocatorApplicationListener

# Application Listeners
org.springframework.context.ApplicationListener=\
org.springframework.boot.autoconfigure.BackgroundPreinitializer

?当程序开始运行的时候,可以看到启动了一个运行的监听器,并且创建了一个springApplicationRunListeners 对象,该对象是一个封装工具类,封装了所有启动监听器。

整体的实例化?

在 EventPublishingRunListener.java

?这在springboot 经常要监听到的,整体监听的数据进行处理。

?在监听器实例化之前,检查是否符合固定的类型

protected boolean supportsEvent(
			ApplicationListener<?> listener, ResolvableType eventType, @Nullable Class<?> sourceType) {
		//判断监听器是否是GenericApplicationListener子类,如不是返回一个GenericApplicationListenerAdapter
		GenericApplicationListener smartListener = (listener instanceof GenericApplicationListener ?
				(GenericApplicationListener) listener : new GenericApplicationListenerAdapter(listener));
		return (smartListener.supportsEventType(eventType) && smartListener.supportsSourceType(sourceType));
	}

此时可以看到GenericApplicationListener类,该类是spring提供的用于重写匹配监听器事件的接口,如果需要判断的监听器是GenericApplicationListener的子类,说明类型匹配方法已被重现,就调用子类的匹配方法,如果不是,提供一个默认的适配器来匹配GenericApplicationListenerAdapter

public boolean supportsEventType(ResolvableType eventType) {
		if (this.delegate instanceof SmartApplicationListener) {
			Class<? extends ApplicationEvent> eventClass = (Class<? extends ApplicationEvent>) eventType.resolve();
			return (eventClass != null && ((SmartApplicationListener) this.delegate).supportsEventType(eventClass));
		}
		else {
			return (this.declaredEventType == null || this.declaredEventType.isAssignableFrom(eventType));
		}
	}

可以看到该类最终调用的是declaredEventType.isAssignableFrom(eventType)方法,也就是说,如果我们没有重写监听器匹配方法,那么发布的事件 event 会被监听 event以及监听event的父类的监听器监听到。

Springboot内嵌tomcat

在使用springboot搭建一个web应用程序的时候,我们发现不需要自己搭建一个tomcat服务器,只需要引入spring-boot-starter-web,在应用启动时会自动启动嵌入式的tomcat作为服务器,下面来分析下源码的分析流程:

? 之前我们已经讲过了自动装配的原理,其实tomcat的实现机制也是从自动装配开始的。

ServletWebServerFactoryAutoConfiguration类

从这个类上可以看到,当前配置类主要导入了BeanPostProcessorRegister,该类实现了ImportBeanDefinitionRegister接口,可以用来注册额外的BeanDefinition,同时,该类还导入了EmbeddedTomcat,EmbeddedJetty,EmbeddedUndertow三个类,可以根据用户的需求去选择使用哪一个web服务器,默认情况下使用的是tomcat

?当自动装配功能完成之后会接着执行onRefresh的方法(ServletWebServerApplicationContext)

??创建web服务,默认获取的是tomcat的web容器(ServletWebServerApplicationContext)

ServletWebServerApplicationContext?

?DefaultListableBeanFactory

/*
第一个参数type表示要查找的类型
第二个参数表示是否考虑非单例bean
第三个参数表示是否允许提早初始化
*/

@Override
	public String[] getBeanNamesForType(@Nullable Class<?> type, boolean includeNonSingletons, boolean allowEagerInit) {
        //配置还未被冻结或者类型为null或者不允许早期初始化
		if (!isConfigurationFrozen() || type == null || !allowEagerInit) {
			return doGetBeanNamesForType(ResolvableType.forRawClass(type), includeNonSingletons, allowEagerInit);
		}
        //此处注意isConfigurationFrozen为false的时候表示beanDefinition可能还会发生更改和添加,所以不能进行缓存,如果允许非单例bean,那么从保存所有bean的集合中获取,否则从单例bean中获取
		Map<Class<?>, String[]> cache =
				(includeNonSingletons ? this.allBeanNamesByType : this.singletonBeanNamesByType);
		String[] resolvedBeanNames = cache.get(type);
		if (resolvedBeanNames != null) {
			return resolvedBeanNames;
		}
        //如果缓存中没有获取到,那么只能重新获取,获取到之后就存入缓存
		resolvedBeanNames = doGetBeanNamesForType(ResolvableType.forRawClass(type), includeNonSingletons, true);
		if (ClassUtils.isCacheSafe(type, getBeanClassLoader())) {
			cache.put(type, resolvedBeanNames);
		}
		return resolvedBeanNames;
	}

?默认启动的方法。

?完成内嵌tomcat的api调用(TomcatServletWebServerFactory)

?

?获取tomcat服务(TomcatServletWebServerFactory)

protected TomcatWebServer getTomcatWebServer(Tomcat tomcat) {
	return new TomcatWebServer(tomcat, getPort() >= 0);
}
public TomcatWebServer(Tomcat tomcat, boolean autoStart) {
	Assert.notNull(tomcat, "Tomcat Server must not be null");
	this.tomcat = tomcat;
	this.autoStart = autoStart;
    //初始化
	initialize();
}

完成tomcat的初始化

?除了refresh方法之外,在finishRefresh()方法中也对tomcat做了相关的处理(ServletWebServerApplicationContext)

其实最后应用上下文关闭时会调用tomcat的关闭

在refreshContext中注册一个关闭的钩子函数,而钩子函数可以完成关闭的功能

ServletWebServerApplicationContext

@Override
	protected void onClose() {
		super.onClose();
		stopAndReleaseWebServer();
	}

整个tomcat整和到springboot里面了 ,具体在源码中看一遍你就明白了,主要是理解原理,去推,可以自己看时,跟着走走,比较晕,但是 走一遍,也不是特别那个。

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2022-10-31 11:40:47  更:2022-10-31 11:45:50 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/19 10:19:38-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码