欢迎来到皮皮网网首页

【365源码】【exe软件源码导出】【软件测试源码时代】springboot底层源码_深入剖析springboot源码

来源:tc源码脚本 时间:2024-11-24 11:47:39

1.springboot安装及配置?
2.Spring Boot Redis 底层Cluster 实战干货
3.Springboot基于Redisson实现Redis分布式可重入锁案例到源码分析
4.spring启动原理(spring工程启动)
5.Spring Boot 把 Maven 干掉了,拥抱 Gradle!源码源码

springboot底层源码_深入剖析springboot源码

springboot安装及配置?

       SpringBoot教程第篇:整合elk,深入搭建实时日志平台

       这篇文章主要介绍springboot整合elk.

       elk简介

       elk下载安装

       elk下载地址:

       建议在linux上运行,剖析elk在windows上支持得不好,底层另外需要jdk1.8的源码源码365源码支持,需要提前安装好jdk.

       下载完之后:安装,深入以logstash为栗子:

       配置、剖析启动Elasticsearch

       打开Elasticsearch的底层配置文件:

       修改配置:

       network.host=localhost

       network.port=

       它默认就是这个配置,没有特殊要求,源码源码在本地不需要修改。深入

       启动Elasticsearch

       启动成功,剖析访问localhost:,底层网页显示:

       配置、启动logstash

       在logstash的源码源码主目录下:

       修改log4j_to_es.conf如下:

       input{

       log4j{

       mode="server"

       host="localhost"

       port=

       }

       }

       filter{

       #Onlymatcheddataaresendtooutput.

       }

       output{

       elasticsearch{

       action="index"#TheoperationonES

       hosts="localhost:"#ElasticSearchhost,canbearray.

       index="applog"#Theindextowritedatato.

       }

       }

       修改完配置后启动:

       ./bin/logstash-fconfig/log4j_to_es.conf

       终端显示如下:

       访问localhost:

       证明logstash启动成功。

       配置、深入启动kibana

       到kibana的安装目录:

       默认配置即可。

       访问localhost:,网页显示:

       证明启动成功。

       创建springboot工程

       起步依赖如下:

       log4j的配置,/src/resources/log4j.properties如下:

       log4j.rootLogger=INFO,console

       #forpackagecom.demo.elk,logwouldbesenttosocketappender.

       log4j.logger.com.forezp=DEBUG,socket

       #appendersocket

       log4j.appender.socket=org.apache.log4j.net.SocketAppender

       log4j.appender.socket.Port=

       log4j.appender.socket.RemoteHost=localhost

       log4j.appender.socket.layout=org.apache.log4j.PatternLayout

       log4j.appender.socket.layout.ConversionPattern=%d[%-5p][%l]%m%n

       log4j.appender.socket.ReconnectionDelay=

       #appenderconsole

       log4j.appender.console=org.apache.log4j.ConsoleAppender

       log4j.appender.console.target=System.out

       log4j.appender.console.layout=org.apache.log4j.PatternLayout

       log4j.appender.console.layout.ConversionPattern=%d[%-5p][%l]%m%n

       打印log测试:

       在kibana实时监控日志

       打开localhost::

       Management=indexpattrns=addnew:

       点击discovery:

       springboot配置文件总结

       springboot本身支持多种灵活的配置方式,为开发springboot程序带来了很大的灵活性和扩展性,但是同时由于太灵活,经常会导致明明配置了相关属性,却没有生效。

       本文总结了springboot配置文件的原理以及多个配置文件生效的顺序。

       springboot配置文件支持灵活的路径,以及灵活的文件名,用一个变量表达式总结如下:

       部分源码如下:

       当满足上述变量表达式的配置文件有多个时,会有一个配置的优先级。假设

       上面每个条件组合起来,则最多有配置文件如下,且顺序从上到下:

       获取属性时,按从上到下的exe软件源码导出顺序遍历由上述文件生成的属性资源对象PropertySource,如果遇到匹配的key直接返回。

       总结一下:就是如果同一个key的属性只出现一次,则直接取该值即可。如果同一个key的属性出现多次,则取顺序靠前的属性资源对象。另外其中每个文件都是可选的。

       需要注意的一点是:如果在同一个location下配置了多个文件名一样的文件,则只会取一个,比如在classpath:/,有如下两个文件application.yml:

       则只会根据classloader的classpath列表,选取第一个出现的文件。因为springboot加载配置文件时最底层是使用的下面的方法:

       这两个方法只会获取classloader类的ucp属性里面第一个匹配到的值。如果对springboot自身的机制不满意,想获取所有的classpath:/路径下面的applicaiton.yml文件,可以使用下面的方法:

       本文总结了springboot配置文件的原理以及多个配置文件生效的顺序。如果存在增加了配置文件或者在配置文件里面增加了属性却没有生效,可以参考上面的springboot配置文件表达式和配置文件生效顺序进行排查。

       后面还会有一篇文章讨论基于springboot配置原理如何实现自定义的配置读取方式。

springboot插件安装(JBLSpringBootAppGen)

       插件安装

       在应用springboot工程的时候;一般情况下都需要创建启动引导类Application.java和application.yml配置文件,而且内容都是一样的;为了便捷可以安装一个IDEA的插件JBLSpringBootAppGen在项目上右击之后可以自动生成启动引导类Application.java和application.yml配置文件。

       使用

       新建任意一个maven工程,右击工程,选择JBLSpringBootAppGen

       是否添加application.properties文件

       点击OK,工具会自动帮忙创建

SpringBoot配置文件详解(告别XML)

       快速学会和掌握SpringBoot的核心配置文件的使用。

       SpringBoot提供了丰富的外部配置,常见的有:

       其中核心配置文件我们并不陌生,主要以Key-Value的形式进行配置,其中属性Key主要分为两种:

       在application.properties添加配置如下:

       ①添加数据源信息

       在application.propertis添加配置如下:

       ①添加认证信息,其中socks.indentity.*是自定义的属性前缀。

       ②添加随机值,其中spring.test.*是自定义的属性前缀。

       使用方法:@ConfigurationProperties(prefix="spring.datasource")

       使用说明:提供Setter方法和标记组件Component

       如何验证是软件测试源码时代否成功读取配置?答:这里可以简单做个验证,注入MyDataSource,使用Debug模式可以看到如下信息:

       使用方法:@Value("spring.datasource.*")

       使用说明:提供Setter方法和标记组件Component

       注意事项:@Value不支持注入静态变量,可间接通过Setter注入来实现。

       关于两者的简单功能对比:

       显然,前者支持松绑定的特性更强大,所以在实际开发中建议使用@ConfigurationProperties来读取自定义属性。

       SpringBoot默认会加载这些路径加载核心配置文件,按优先级从高到低进行排列:具体规则详见ConfigFileApplicationListener

       如果存在多个配置文件,则严格按照优先级进行覆盖,最高者胜出:

       举个简单的例子,例如再上述位置都有一个application.properties,并且每个文件都写入了server.port=xx(xx分别是,,,),在启动成功之后,最终应用的端口为:。图例:

       如果想修改默认的加载路径或者调改默认的配置文件名,我们可以借助命令行参数进行指定,例如:

       YAML是JSON的一个超集,是一种可轻松定义层次结构的数据格式。

       答:因为配置文件这东西,结构化越早接触越规范越好。这里推荐阅读阮一峰老师写的YAML语言教程,写的很简单明了。

       引入依赖:在POM文件引入snakeyaml的依赖。

       使用说明:直接在类路径添加application.yml即可。

       例如下面这两段配置是完全等价的:

       ①在application.yml配置数据源:

       ②在application.properties配置数据源:

       在项目的实际开发中,我们往往需要根据不同的环境来加载不同的配置文件。例如生产环境,测试环境和开发环境等。此时,外卖商家助手源码我们可以借助Profiles来指定加载哪些配置文件。例如:

       温馨提示:如果spring.profiles.active指定了多个配置文件,则按顺序加载,其中最后的优先级最高,也就是最后的会覆盖前者。

       使用方法:

       使用Maven插件打包好项目,然后在当前路径,执行DOS命令:java-jardemo.jar--server.port=,在控制台可看到应用端口变成了。

       实现原理:

       默认情况下,SpringBoot会将这些命令行参数转化成一个Property,并将其添加到Environment上下文。

       温馨提示:

       由于命令行参数优先级非常之高,基本高于所有常见的外部配置,所以使用的时候要谨慎。详见PropertySource执行顺序。

       关闭方法:

       如果想禁用命令行属性,可以设置如下操作:springApplication.setAddCommandLineProperties(false)

Springboot配置logback

       因为logback其他配置尚好理解,本文只说明比较少用,但是却起关键作用的两个子节点。

       1、依赖:

       实际开发中我们不需要直接添加该依赖,你会发现spring-boot-starter其中包含了spring-boot-starter-logging,SpringBoot为我们提供了很多默认的日志配置,所以,只要将spring-boot-starter-logging作为依赖加入到当前应用的classpath,则“开箱即用”。

       2、日记的等级

       日志级别从低到高分为TRACEDEBUGINFOWARNERRORFATAL

       3、配置

       这里对日志框架的支持有两种配置方式,一般来讲我们倘若不是要较复杂的需求,可以直接在?倚天2欧版源码application.yml?配置文件配置下即可:

       application.properties或?application.yml?(系统层面)

       参考网站:

       logback-spring.xml?(自定义文件方式)

       参考网站:

       4、彩色打印

       参考:

       5、@Slf4j注解

       安装lombok插件,在需要打印的类名上加上该注解即可

       替代下面语句的编写

       privateLoggerlogger=LoggerFactory.getLogger(this.getClass());

       6、打印不出json的问题

       不是打印不出而是正确的要加一个占位符{ },如下

       log.info("hospital{ }",JSON.toJSONString(hospitalEntity2));

       7、log存放文件路径定义

       最关键的两个节点,你可以理解之前的property、appender嵌套property只是一些定义好的变量,真正定义方法怎么去运用这些变量是这两个节点所要做的。

       1、子节点--root

       root节点是必选节点,用来指定最基础的日志输出级别,只有一个level属性,不区分大小写,默认是DEBUG。

       可以包含零个或多个元素,标识这个appender将会添加到这个loger(理解root为一个全局的loger)。

       举例子:

       上图这是我定义好的文件输出的appender节点,对应下图的appender-ref节点,ref对应appender的name属性,上面说到root节点好比一个方法,所以现在这个方法的意思是全局打印等级为INFO,而且四个appender变量都执行,即正常的控制台输出和warn、info、error的三个文件输出,可以到对应的控制台和日志文件里面看到的确有日志。反之倘若我们level定为Debug,或者去除name为“WARN”的appender则是输出Debug以上等级的日志,WARN.log日志文件也不会再有日志打印进去。

       2、子节点--loger

       loger用来设置某一个包或者具体的某一个类的日志打印级别、以及指定appender,也就是只管辖指定的区域的日志输出规则。loger仅有一个name属性,一个可选的level和一个可选的addtivity属性。

       注意:这里说的上级就是root节点

       name:用来指定受此loger约束的某一个包或者具体的某一个类。

       level:用来设置打印级别,大小写无关:TRACE,DEBUG,INFO,WARN,ERROR,ALL和OFF,还有一个特俗值INHERITED或者同义词NULL,代表强制执行上级的级别。如果未设置此属性,那么当前loger将会继承上级的级别。

       addtivity:是否向上级loger传递打印信息。默认是true。

       举例子:

       控制com.dudu.controller.LearnController类的日志打印,打印级别为“WARN”;

       additivity属性为false,表示此loger的打印信息不再向上级传递;

       指定了名字为“console”的appender;

       这时候执行com.dudu.controller.LearnController类的login方法时,先执行loggername="com.dudu.controller.LearnController"level="WARN"additivity="false",

       将级别为“WARN”及大于“WARN”的日志信息交给此loger指定的名为“console”的appender处理,在控制台中打出日志,不再向上级root传递打印信息。

       注意:

       当然如果你把additivity=”false”改成additivity=”true”的话,就会打印两次,因为打印信息向上级传递,logger本身打印一次,root接到后又打印一次。

       四、配合多环境

       据不同环境(prod:生产环境,test:测试环境,dev:开发环境)来定义不同的日志输出,在logback-spring.xml中使用springProfile节点来定义,方法如下:

       文件名称不是logback.xml,想使用spring扩展profile支持,要以logback-spring.xml命名

       可以启动服务的时候指定profile(如不指定使用默认),如指定prod的方式为:

       java-jarxxx.jar–spring.profiles.active=prod

       关于多环境配置可以参考

       SpringBoot干货系列:(二)配置文件解析

Spring Boot Redis Cluster 实战干货

       只需添加3个master节点,3个slave节点无需添加。

       配置完成这些即可,Spring Boot 会自动完成其他配置。

       现在可以像使用单机一样使用集群,Redis 会自动按key分片到不同的集群实例。

       遇到的问题:尝试向Redis写入数据时,出现无法获取连接异常,经过长时间代码追踪,发现连接的是.0.0.1,而非配置的..1.8,这令人困惑。继续追踪代码发现是向Redis服务器获取的集群实例列表,真是坑!

       源码:redis.clients.jedis.Jedis#clusterSlots

       就是这里获取返回的集群列表,返回的就是.0.0.1,而非配置的..1.8。

       最后修改各个集群节点的配置文件redis.conf,添加:

       重启集群节点后,读写恢复正常。

       更多 Spring Boot 干货:

       Spring Boot 宣布移除 run 命令,真让我猝不及防!

       Spring Boot 定时任务开启后,如何自动停止符合条件?

       Spring Boot 保护敏感配置的 4 种方法,让你的系统不再裸奔!!

       Spring Boot 集成 Flyway,数据库也能做版本控制,太牛逼了!

        个官方 Spring Boot Starters 出炉!别再重复造轮子了……

       Spring Boot Redis 实现分布式锁,真香!!

       Spring Boot 之配置导入,强大到不行!

       年轻人的第一个自定义 Spring Boot Starter!

       Spring Boot 面试,一个问题就干趴下了!(下)

       Spring Boot 最核心的 个注解,都是干货!

       好了,最后栈长再送你一份Spring Boot 学习笔记,包括底层实现原理及代码实战,非常齐全,助你快速打通 Spring Boot 的各个环节。

       链接: pan.baidu.com/s/wLzA6...

       提取码: ztsj

       版权申明:本文系 "Java技术栈" 原创,原创实属不易,转载、引用本文内容请注明出处,禁止抄袭、洗稿,请自重,尊重他人劳动成果和知识产权。

Springboot基于Redisson实现Redis分布式可重入锁案例到源码分析

       一、前言

       实现Redis分布式锁,最初常使用SET命令,配合Lua脚本确保原子性。然而手动操作较为繁琐,官网推荐使用Redisson,简化了分布式锁的实现。本文将从官网至整合Springboot,直至深入源码分析,以单节点为例,详细解析Redisson如何实现分布式锁。

       二、为什么使用Redisson

       通过访问Redis中文官网,我们发现官方明确指出Java版分布式锁推荐使用Redisson。官网提供了详细的文档和结构介绍,帮助开发者快速上手。

       三、Springboot整合Redisson

       为了实现与Springboot的集成,首先导入Redisson依赖。接下来,参照官网指导进行配置,并编写配置类。结合官网提供的加锁示例,编写简单的Controller接口,最终测试其功能。

       四、lock.lock()源码分析

       在RedissonLock实现类中,`lock`方法的实现揭示了锁获取的流程。深入至`tryLockInnerAsync`方法,发现其核心逻辑。进一步调用`scheduleExpirationRenewal`方法,用于定时刷新锁的过期时间,确保锁的有效性。此过程展示了锁实现的高效与自适应性。

       五、lock.lock(, TimeUnit.SECONDS)源码分析

       当使用带有超时时间的`lock`方法时,实际调用的逻辑与常规版本类似,关键差异在于`leaseTime`参数的不同设置。这允许开发者根据需求灵活控制锁的持有时间。

       六、lock.unlock()源码分析

       解锁操作通过`unlockAsync`方法实现,进一步调用`unlockInnerAsync`方法完成。这一过程确保了锁的释放过程也是异步的,增强了系统的并发处理能力。

       七、总结

       通过本文,我们跟随作者深入Redisson的底层源码,理解了分布式锁的实现机制。这一过程不仅提升了对Redisson的理解,也激发了面对复杂技术挑战时的勇气。希望每位开发者都能勇敢探索技术的边界,共同进步。欢迎关注公众号,获取更多技术文章首发信息。

spring启动原理(spring工程启动)

       SpringBoot启动原理分析

       è‡ªåŠ¨é…ç½®æ ¸å¿ƒç±»SpringFactoriesLoader

       ä¸Šé¢åœ¨è¯´@EnableAutoConfiguration的时候有说META-INF下的spring.factories文件,那么这个文件是怎么被spring加载到的呢,其实就是SpringFactoriesLoader类。

       SpringFactoriesLoader是一个供Spring内部使用的通用工厂装载器宏闭,SpringFactoriesLoader里有两个方法,

       åœ¨è¿™ä¸ªSpringBoot应用启动过程中,SpringFactoriesLoader做了以下几件事:

       åŠ è½½æ‰€æœ‰META-INF/spring.factories中的Initializer

       åŠ è½½æ‰€æœ‰META-INF/spring.factories中的Listener

       åŠ è½½EnvironmentPostProcessor(允许在Spring应用构建之前定制环境配置)

       æŽ¥ä¸‹æ¥åŠ è½½Properties和YAML的PropertySourceLoader(针对SpringBoot的两种配置文件的加载器)

       å„种异常情况的FailureAnalyzer(异常解释器)

       åŠ è½½SpringBoot内部实现的各种AutoConfiguration

       æ¨¡æ¿å¼•æ“ŽTemplateAvailabilityProvider(如Freemarker、Thymeleaf、Jsp、Velocity等)

       æ€»å¾—来说,SpringFactoriesLoader和@EnableAutoConfiguration配合起来,整体功能就是查找spring.factories文件,加载自动配置类。

       æ•´ä½“启动流程

       åœ¨æˆ‘们执行入口类的main方法之后,运行SpringApplication.run,后面new了一个SpringApplication对象,然后执行它的run方法。

       åˆå§‹åŒ–SpringApplicationç±»

       åˆ›å»ºä¸€ä¸ªSpringApplication对象时,会调用它自己的initialize方法

       æ‰§è¡Œæ ¸å¿ƒrun方法

       åˆå§‹åŒ–initialize方法执行完之后,会调用run方法,开始启动SpringBoot。

       é¦–先遍历执行所有通过SpringFactoriesLoader,在当前classpath下的META-INF/spring.factories中查找所有可用的SpringApplicationRunListeners并实例化。调用它们的starting()方法,液蔽通知这些监听器SpringBoot应用启动。

       åˆ›å»ºå¹¶é…ç½®å½“前SpringBoot应用将要使用的Environment,包括当前有效的PropertySource以及Profile。

       éåŽ†è°ƒç”¨æ‰€æœ‰çš„SpringApplicationRunListeners的environmentPrepared()的方法,通知这些监听器SpringBoot应用的Environment已经完成初始化。

       æ‰“印SpringBoot应用的banner,SpringApplication的showBanner属性为true时,如果classpath下存在banner.txt文件,则打印其内容,否则打印默认banner。

       æ ¹æ®å¯åŠ¨æ—¶è®¾ç½®çš„applicationContextClass和在initialize方法设置的webEnvironment,创建对应的applicationContext。

       åˆ›å»ºå¼‚常解析器,用在启动中发生异常的时候进行异常处理(包括记录日志、释放资源等)。

       è®¾ç½®SpringBoot的Environment,注册SpringBean名称的序列化器BeanNameGenerator,并设置资源加载器ResourceLoader,通过SpringFactoriesLoader加载ApplicationContextInitializer初始化器,调用initialize方法,对创建的ApplicationContext进一步初始化。

       è°ƒç”¨æ‰€æœ‰çš„SpringApplicationRunListeners的contextPrepared方法,通知闹绝州这些Listener当前ApplicationContext已经创建完毕。

       æœ€æ ¸å¿ƒçš„一步,将之前通过@EnableAutoConfiguration获取的所有配置以及其他形式的IoC容器配置加载到已经准备完毕的ApplicationContext。

       è°ƒç”¨æ‰€æœ‰çš„SpringApplicationRunListener的contextLoaded方法,加载准备完毕的ApplicationContext。

       è°ƒç”¨refreshContext,注册一个关闭Spring容器的钩子ShutdownHook,当程序在停止的时候释放资源(包括:销毁Bean,关闭SpringBean的创建工厂等)

       æ³¨ï¼šé’©å­å¯ä»¥åœ¨ä»¥ä¸‹å‡ ç§åœºæ™¯ä¸­è¢«è°ƒç”¨ï¼š

       1)程序正常退出

       2)使用System.exit()

       3)终端使用Ctrl+C触发的中断

       4)系统关闭

       5)使用Killpid命令杀死进程

       èŽ·å–当前所有ApplicationRunner和CommandLineRunner接口的实现类,执行其run方法

       éåŽ†æ‰€æœ‰çš„SpringApplicationRunListener的finished()方法,完成SpringBoot的启动。

       spring工作原理

       Spring的工作原理是让一个对象的创建不用new就可以自动的生产,在运行时与xmlSpring的配置文件来高岩动态的创建对象和调用对象,而不需要通过代码来关联。

       Spring是一个开放源代码的设计层面框架,他解决的是业务逻辑层和其他各层的松耦合问题,因此它将面向接口的编程思想贯穿整个系统应用。

       spring特点是1.方便解耦,简化开发。2.AOP编程的支持。3.声明式事务的支持。4.方便程序的测试。5.方便集成各种优秀框架。6.降低JavaEEAPI的使用难度。7.Java源码是经典学习范例。

       Spring框架是由于软件开发的复杂性而创建的。Spring使用的是基本的JavaBean来完成以前只可能由EJB完成的事情。然而,Spring的用途不仅仅限于服务器端的开发。从简单性、可测试性和松耦合性角度而言,绝大部分Java应用都可以从Spring中带消受益。Spring是一个轻量级的控制反转(IoC)和面向切面(AOP)的容器框架。

       Spring通过一种称作控制反转(IoC)的技术促进了松耦合。当应用了IoC,一个对象依赖的其它对象会通过被动的方式传递进来,而不是这个对象自己创建或者查找依赖对象。你可以认为IoC与JNDI相反——不是对象从容器中查找依赖,而是容器在对象初戚行御始化时不等对象请求就主动将依赖传递给它。

spring的原理是什么?

       ä¸€ã€IoC(Inversionofcontrol):控制反转\x0d\1、IoC:\x0d\概念:控制权由对象本身转向容器;由容器根据配置蠢衫文件去创建实例并创建各个实例之间的依赖关系\x0d\核心:bean工厂;在Spring中,bean工厂创建的各个实例称作bean\x0d\二、AOP(Aspect-OrientedProgramming):面向方面编程。\x0d\1、代理的两种方式:\x0d\静态代理:\x0d\针对每个具体类分别编写代理类。\x0d\针对一个接口编写一个代理类。\x0d\动态代理:\x0d\针对一个方面编写一个InvocationHandler,然后借用JDK反射包中的Proxy类为各种接口动态生成相应的代理类。\x0d\2、AOP的主要原理:动态代理。\x0d\Spring工作原理\x0d\Spring已经用过一段时间了,感觉Spring是个很不错的框架。内部最核心的就是IOC了,\x0d\动态注入,让一个对象的创建不用new了,可以自动的生产,这其实就是利用java里的反射,反射其实就是在运行时动态的去创建、调用对象,Spring就是在运行时,跟xmlSpring的配置文件来动态的创建对象,和调用对象里的方法的。\x0d\Spring还有一个核心就是AOP这个就是面向切面编程,可以为某一类对象进行监督和控制(也就是在调用这类对象的具体方法的前后去调用你指定的模块)从而达到对一个模块扩充的功能。这些都是通过配置类达到谈庆的。\x0d\Spring目的含档握:就是让对象与对象(模块与模块)之间的关系没有通过代码来关联,都是通过配置类说明管理的(Spring根据这些配置内部通过反射去动态的组装对象)\x0d\要记住:Spring是一个容器,凡是在容器里的对象才会有Spring所提供的这些服务和功能。\x0d\Spring里用的最经典的一个设计模式就是:模板方法模式。

SpringBoot应用启动原理(二)扩展URLClassLoader实现嵌套jar加载

       åœ¨ä¸Šç¯‡æ–‡ç« ã€ŠSpringBoot应用启动原理(一)将启动脚本嵌入jar》中介绍了SpringBoot如何将启动脚本与RunnableJar整合为ExecutableJar的原理,使得生成的jar/war文件可以直接启动

       æœ¬ç¯‡å°†ä»‹ç»SpringBoot如何扩展URLClassLoader实现嵌套jar的类(资源)加载,以启动我们的应友枣旁用。

       é¦–先岩伏,从一个简单的示例开始

       build.gradle

       WebApp.java

       æ‰§è¡Œgradlebuild构建jar包,里面包含应用程序、第三方依赖以及SpringBoot启动程序,其目录结构如下

       æŸ¥çœ‹MANIFEST.MF的内容(MANIFEST.MF文件的作用请自行GOOGLE)

       å¯ä»¥çœ‹åˆ°ï¼Œjar的启动类为org.springframework.boot.loader.JarLauncher,而并不是我们的com.manerfan.SpringBoot.theory.WebApp,应用程序入口类被标记为了Start-Class

       jar启动并不是通过应用程序入口类,而是通过JarLauncher代理启动。其实SpringBoot拥有3中不同的Launcher:JarLauncher、WarLauncher、PropertiesLauncher

       SpringBoot使用Launcher代理启动,其最重要的一点便是可以自定义ClassLoader,以实现对jar文件内(jarinjar)或其他路径下jar、class或资源文件的加载

       å…³äºŽClassLoader的更多介绍可参考《深入理解JVM之ClassLoader》

       SpringBoot抽象了Archive的概念,一个Archive可以是jar(JarFileArchive),可以是一个文件目录(ExplodedArchive),可以抽象为统一访问资源的逻辑层。

       ä¸Šä¾‹ä¸­ï¼Œspring-boot-theory-1.0.0.jar既为一个JarFileArchive,spring-boot-theory-1.0.0.jar!/BOOT-INF/lib下的每一个jar包也是一个JarFileArchive

       å°†spring-boot-theory-1.0.0.jar解压到目录spring-boot-theory-1.0.0,则目录spring-boot-theory-1.0.0为一个ExplodedArchive

       æŒ‰ç…§å®šä¹‰ï¼ŒJarLauncher可以加载内部/BOOT-INF/lib下的jar及/BOOT-INF/classes下的应用class

       å…¶å®žJarLauncher实现很简单

       å…¶ä¸»å…¥å£æ–°å»ºäº†JarLauncher并调用父类Launcher中的launch方法启动程序

       å†åˆ›å»ºJarLauncher时,父类ExecutableArchiveLauncher找到自己所在的jar,并创建archive

       åœ¨Launcher的launch方法中,通过以上archive的getNestedArchives方法找到/BOOT-INF/lib下所有jar及/BOOT-INF/classes目录所对应的archive,通过这些archives的url生成LaunchedURLClassLoader,并将其设置为线程好橡上下文类加载器,启动应用

       è‡³æ­¤ï¼Œæ‰æ‰§è¡Œæˆ‘们应用程序主入口类的main方法,所有应用程序类文件均可通过/BOOT-INF/classes加载,所有依赖的第三方jar均可通过/BOOT-INF/lib加载

       åœ¨åˆ†æžLaunchedURLClassLoader前,首先了解一下URLStreamHandler

       java中定义了URL的概念,并实现多种URL协议(见URL)*/s/wLzA6... 提取码为 ztsj,希望这份学习笔记能够帮助你快速掌握 Spring Boot 的核心知识。

       学习之路永无止境,不断探索、实践,才能不断进步。更多关于 Spring Boot 的深入学习资源和教程,欢迎关注 Java技术栈。如果你觉得本文对你有所启发,不妨点个在看、转发,你的支持是栈长持续分享的动力。