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就完成了。

你可能感兴趣的:(spring starter原理和实例)