SpringBoot原理
该文章均总结自B站,视频ID:BV1Et411Y7tQ
中的P18、P31、P67、P68、P70
1. Spring自动配置原理
来自视频:P18
SpringBoot启动时加载的主配置类并且开启的自动配置功能@EnableAutoConfiguration
;
1.1 自动配置组件
这个注解的作用就是利用EnableAutoConfigurationImprotSelector
给容器中导入了一些组件,使用SpringFactoriesLoader.loadFactoryNames()
来扫描jar类路径下的 META-INF/spring.factories,将扫描到的文件内容包装成properties对象,从properties中获取的EnableAutoConfiguration.class
类(类名)对应的值,把他们添加到容器中。也就是说将EnableAutoConfiguration
类中的的值加入到了容器中。
1.2自动配置类
只有当自动配置组件加入到容器中后,才能使用自动配置类来做自动配置。每一个自动配置类用户进行自动配置功能;所有在配置文件中能配置的属性,都是在XXXProperties类中封装。@EnableConfigurationProperties(xxx.class)
与配置文件中对应的值绑定起来 @ConditionalOnWebApplication
判断当前应用是否为web应用,如果是,当前配置类生效。@ConditionalOnClass(xxx.class)
判断当前项目中有没有指定的类。
@ConditionalOnProperty
判断配置文件中是否存在某个配置,即使不存在(配置)也有默认值会生效。
根据当前不同的条件进行判断,决定这个配置类是否生效,生效之后就会给容器中添加各种组件,组件的属性在对应的properties中获取的,每一个属性又是和配置文件绑定的。
精髓:
- 只要自动配置类中配置了需要的组件,就不需要再次配置了。
- 没有就需要去配置文件中进行配置
- 给容器中自动配置类添加组件的时候,会从properties类中获取某些属性这些属性就可以再配置文件中指定它的值。
2.SpringMVC自动配置原理
P31
SpringBoot对SpringMVC自动默认配置:
- ViewResolver:决定如何渲染,定制视图解析器:给容器中添加一个视图解析器,SpringMVC会自动将其组合起来。
- Converter:类型转换器,自己添加的格式化器和转换器,只需要放在容器中即可。
- Formatter:格式化器;自己添加的格式化器和转换器,只需要放在容器中即可。
- HttpMessageConverter:SpringMVC用来处理转换HTTP请求和响应的,自己添加时,只需要将自己的组件注册到容器中。
- MessageCodesResolver:定义错误代码生成规则
- ConfigurableWebBindingInitializer:可以自己配置一个加入到容器中来替换默认的;作用是初始化Web核心绑定器。
修改SpringBoot默认配置:
- 添加组件: 如果有用户配置的,优先使用用户配置的;没有才自动配置;如果可以有多个就将默认配置组合。
3. 创建SpringApplication
P67
启动流程:
创建SpringApplication对象:调用intitiialie()
方法
4.启动应用
P68
运行run方法
public ConfigurableApplicationContext run(String... args) {
StopWatch stopWatch = new StopWatch();
stopWatch.start();
ConfigurableApplicationContext context = null;
Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
configureHeadlessProperty();
//获取SpringApplicationRunListeners;从类路径下META-INF/spring.factories
SpringApplicationRunListeners listeners = getRunListeners(args);
//回调所有的starting()方法
listeners.starting();
try {
//封装命令行参数
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
//准备环境
ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);//创建环境完成后回调SpringApplicationRunListeners.environmentPrepared()方法;表示环境准备完成。
configureIgnoreBeanInfo(environment);
//打印SpringBoot图标
Banner printedBanner = printBanner(environment);
//创建ApplicationContext;决定创建web的ioc还是普通的ioc
context = createApplicationContext();
exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class,
new Class[] { ConfigurableApplicationContext.class }, context);
//准备上下文环境;将environment保存到ioc中;
//回调之前保存的所有的ApplicationContextInitializer的initialize()方法;
//回调所有的SpringApplicationRunListener的contextPreared()方法;
prepareContext(context, environment, listeners, applicationArguments, printedBanner);
//prepareContext运行完成后回调所有的SpringApplicationRunListener的contextLoaded()方法
//刷新容器;ioc容器初始化;加载容器的全部组件;如果是we应用会创建嵌入式的Servlet
//扫描,创建,加载所有组件的地方;
refreshContext(context);
//从ioc容器中获取所有的ApplicationRunner和CommandLineRunner进行回调
//ApplicationRunner先回调,CommandLineRunner再回调
afterRefresh(context, applicationArguments);
stopWatch.stop();
if (this.logStartupInfo) {
new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);
}
//所有的SpringApplicationRunListener回调所有的started()方法;发布ApplicationStartedEvent事件
listeners.started(context);
callRunners(context, applicationArguments);
}
catch (Throwable ex) {
handleRunFailure(context, ex, exceptionReporters, listeners);
throw new IllegalStateException(ex);
}
try {
listeners.running(context);
}
catch (Throwable ex) {
handleRunFailure(context, ex, exceptionReporters, null);
throw new IllegalStateException(ex);
}
// 返回启动的IOC容器;里面包含所有的组件
return context;
}
6.自定义starter
P70
启动器只用来做依赖导入;专门来写一个自动配置模块;别人之需要引入启动器(starter)就可以使用;命名方式最好为:xxx-spring-boot-starter