什么是springBoot
使用了特定的方式来进行配置,从而使开发人员不再需要定义样板化的配置。简而言之,Spring Boot通过提供默认配置的方式整合了所有的框架,让我们可以更加简单、快速、方便地构建应用程序。
并不是对spring的功能增强,只是提供了一种快速使用的方式
特性
- 默认提供了大部分框架的使用方式,方便进行快速集成
- Spring Boot应用可以独立运行,符合微服务的开发理念
- Spring Boot内置WEB容器,无需部署WAR包即可运行
- 提供了各种生产就绪型功能,如指标,健康检查和外部配置
- Spring Boot通过网站提供了项目模板,方便项目的初始化
通过以上这些非常优秀的特性,Spring Boot可以帮助我们非常简单、快速的构建起我们的项目,并能够非常方便进行后续开发、测试和部署。
功能
自动配置
起步依赖
嵌入式服务器,无需启动tomcat
起步依赖
spring-boot-starter-parent坐标中配置manager做版本管理
自动配置
基本配置
application文件优先级
properties>yml>yaml
profile
properties文件中指定profile.active = xxx则 application-xxx 被激活使用
或者通过虚拟机参数,java命令行参数指定
条件注解
基于Spring的@Conditional(使用一个实现了match接口的类做bean加载判断逻辑)扩展一系列条件类处理不同的Bean加载条件逻辑。
springboot的所有的条件匹配器都间接的基础了了SpringBootCondition实现了Condition接口。会执行matches方法。
public final boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata)
context为spring上下文,metadata为注解信息
Enable*注解
问题:SpringBoot 无法直接引用别人 jar 包里的 Bean
解决方法
- @ComponentScan 注解扫描配置类所在的包
@ComponentScan("com.xh.config")
需要包名使用不方便
- @Import 注解所导入的类,都会被 Spring 创建,并放入 IOC 容器中
@Import(UserConfig.class)
需要类名也并不方便
- 编写注解 @EnableUser,在注解中使用 @Import 注解导入 UserConfig,并且添加 @Import 的元注解
@Import(UserConfig.class)
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface EnableUser {
}
@Import 注解
@Enable* 底层依赖于 @Import 注解导入一些类,使用 @Import 导入的类会被 Spring 加载到 IOC 容器中。
- 导入Bean
- 导入配置类,配置类中包含的类都将被导入
- 导入 ImportSelector 实现类。类中返回类路径名进行导入,可编码实现动态加载,一般用于加载配置文件中的类
- 导入 ImportBeanDefinitionRegistrar 实现类,使用tBeanDefinition,创建bean,可指定beanname。
@EnableAutoConfiguration
使用import中ImportSelector,
autoconfig包的META-INFO/spring.factories配置文件中定义了需要加载的类名,并且加载时通过condition进行判断
自定义自动配置
https://www.bilibili.com/video/BV1Lq4y1J77x?p=26&vd_source=7c4b5a4832d2c7615beecb45e2752661
- 创建autoconfigure模块
- 创建starter模块,依赖autoconfigure模块
- autoconfigure模块中初始化对象,并定义META-INF/spring.factories文件指定读取properties内容,便于用户自定义对象创建入参
监听机制
基于观察者模式
https://www.jianshu.com/p/bb6a3e631704
获取监听器
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
this.resourceLoader = resourceLoader;
Assert.notNull(primarySources, "PrimarySources must not be null");
this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
this.webApplicationType = WebApplicationType.deduceFromClasspath();
setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
this.mainApplicationClass = deduceMainApplicationClass();
}
构建发布器
public EventPublishingRunListener(SpringApplication application, String[] args) {
this.application = application;
this.args = args;
this.initialMulticaster = new SimpleApplicationEventMulticaster();
for (ApplicationListener<?> listener : application.getListeners()) {
this.initialMulticaster.addApplicationListener(listener);
}
}
事件发布
@Override
public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {
ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
Executor executor = getTaskExecutor();
for (ApplicationListener<?> listener : getApplicationListeners(event, type)) {
if (executor != null) {
executor.execute(() -> invokeListener(listener, event));
}
else {
invokeListener(listener, event);
}
}
}
监控功能
actuator