spring starter原理和实例

1.背景

springboot的一个优势就是starter,利用starter,可以避免一些的繁琐的配置,将starter里面的功能开箱即用。例如:spring-boot-starter-jpa等,只需要配置一下数据连接信息,就可以进行数据库操作。当然starter技术也没有想象的高大上,最终也是一行行代码实现的,目前就让我们一起看一下接下面纱的starter。

2.spring starter实现原理

在META-INF/spring.factories文件中通过配置的key=value1,value2,...的方式,配置starter中自动配置的类,然后在springboot启动的时候,解析jar中的META-INF/spring.factories文件,将其通过一定的规则加载到当前的线程,通过代码调试目前发现可以在META-INF/spring.factories中添加如下几种配置:

spring.factories支持配置类型
spring.factories中的类型

接下来一起看一下SpringBoot在启动的时候,将spring.factories配置加载到进程中的步骤:

创建SpringBoot程序,默认在启动类中生成一个入口函数:

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

从在个主函数跟着代码进去,可以看见在SpringAppplication中具体实现,就是创建一个SpringApplication实例,然后运行run方法,starter加载机制也就是在这个过程中实现的。

public static ConfigurableApplicationContext run(Class<?>[] primarySources, String[] args) {

return new SpringApplication(primarySources).run(args);}

接下来看一下SpringApplication的创建过程:通过getSpringFactoriesInstances方法读取spring.factories中ApplicationContextInitializer,ApplicationListener配置项。

创建SpringApplication

看一下getSpringFactoriesInstances读取spring.facotpries的细节见下图

spring.factories读取的细节

接下来看一下run方法

run方法

前面的代码不用分析,主要是准备对象,我们从 SpringApplicationRunListeners listeners = getRunListeners(args)开始分析,

第一步:是从类路径下META-INF/spring.factories获取SpringApplicationRunListeners,

这个方法跟前面分析的两个获取配置方法类似。

第二步:回调所有的获取SpringApplicationRunListener.starting()方法。

第三步: 封装命令行参数。

第四步:准备环境,调用prepareEnvironment方法。

第五步:打印Banner图(就是启动时的标识图)。

第六步:创建ApplicationContext,决定创建web的ioc还是普通的ioc。

第七步:异常分析报告。

第八步:准备上下文环境,将environment保存到ioc中

第九步:刷新容器,ioc容器初始化(如果是web应用还会创建嵌入式的Tomcat),这个就是扫描,创建,加载所有组件的地方,(配置类,组件,自动配置)。

第十步:所有的SpringApplicationRunListener回调started方法。

第十一步:从ioc容器中获取所有的ApplicationRunner和CommandLineRunner进行回调,ApplicationRunner先回调,CommandLineRunner再回调。

第十二步:所有的SpringApplicationRunListener回调running方法。

第十三步:整个SpringBoot应用启动完成以后返回启动的ioc容器。

其中refreshContext(context)实际调用的AbstractApllicationContext#refresh(),也是在这个里面读取经常使用的EnableAutoConfiguration,refresh()#invokeBeanFactoryPostProcessors()方法中间会调用ConfigurationClassParser#processImports方法,获取到AutoConfigurationImportSelector,调用其selectImports

ConfigurationClassParser#processImports


AutoConfigurationImportSelector#getCandidateConfigurations

3.自定义starter

自定义配置类需要用到的注解如下:

@ConditionalOnBean,仅在当前上下文中存在某个bean时,才会实例化这个Bean。

@ConditionalOnClass,某个class位于类路径上,才会实例化这个Bean。

@ConditionalOnExpression,当表达式为true的时候,才会实例化这个Bean。

@ConditionalOnMissingBean,仅在当前上下文中不存在某个bean时,才会实例化这个Bean。

@ConditionalOnMissingClass,某个class在类路径上不存在的时候,才会实例化这个Bean。

@ConditionalOnNotWebApplication,不是web应用时才会实例化这个Bean。

@AutoConfigureAfter,在某个bean完成自动配置后实例化这个bean。

@AutoConfigureBefore,在某个bean完成自动配置前实例化这个bean

步骤1:创建module,pom.xml需要调整一下:

spring-boot-configuration-processor

spring-boot-configuration-processor 的作用是编译时生成 spring-configuration-metadata.json ,在IDE中编辑配置文件时,会出现提示。

另外打包选择jar-no-fork,因为这里不需要main函数。

jar-no-fork

步骤2:EnableDemoConfiguration

不是必须的,建议有这样一个注释,作为自动配置启动的入口。

EnableDemoConfiguration

步骤3:DemoProperties

name和age对应application.properties里面的demo.name和demo.age

DemoProperties

步骤4:DemoAutoConfiguration

这里设置自动配置的相关条件,和相关操作,由于这里只想写一个最简单的demo,所以这里只需要简单注入一个bean,没有复杂逻辑,实际开发中,这个类是最关键的。

DemoAutoConfiguration

步骤5:DemoService

这里不需要@Service,因为已经通过DemoAutoConfiguration注入spring容器。

DemoService

步骤6:spring.factories

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\com.johar.joharspringstarterautoconfig.DemoAutoConfiguration

步骤7:本地mvn install之后,在新的spring-boot项目里面引入自定义的jar,然后在启动类中开启配置。

AutoconfigDemoApplication

在配置文件application.properties中配置demo.age和demo.name

配置文件

启动main函数,控制台会打印出配置文件中的name和age,自定义的spring-boot-starter就完成了。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 195,783评论 5 462
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 82,360评论 2 373
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 142,942评论 0 325
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,507评论 1 267
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,324评论 5 358
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,299评论 1 273
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,685评论 3 386
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,358评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,652评论 1 293
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,704评论 2 312
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,465评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,318评论 3 313
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,711评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,991评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,265评论 1 251
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,661评论 2 342
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,864评论 2 335