SpringBoot源码剖析
-
依赖管理 Spirng-boot-start-parent
问题: (1) 问么导入dependency时可以不用指定版本?
在SpringBoot入门程序中引入的依赖中有个核心依赖
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.5.9</version> <relativePath/> <!-- lookup parent from repository --> </parent>
Ctrl+鼠标左键点击org.springframework.boot进入SpringBoot自带的pom文件中 这里解释了 为什么配置文件要以application开头,要以yml,yaml,properties结尾的原因。
在进入的新pom文件中Ctrl+鼠标左键点击org.springframework.boot进入下一个pom文件,这里对我们常用的依赖做了版本仲裁 所以我们在导入dependency时可以不用加version
需要说明的是,如果我们导入的依赖在SpringBoot中没有申明我们仍然需要加入version。如果想不用SpirngBoot中声明的版本,我们可以在依赖下方加入version 换成自己想要的版本。
-
SpringBoot-starter-web依赖
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency>
引入这个依赖会引入SpringMVC 并且引入tomcat作为内置容器启动
这就是SpringBoot-starter-web依赖引入的依赖
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<version>2.5.9</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-json</artifactId>
<version>2.5.9</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<version>2.5.9</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>5.3.15</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.3.15</version>
<scope>compile</scope>
</dependency>
</dependencies>
SpringBoot除了Web依赖启动器 还有其他的场景启动器
https://docs.spring.io/spring-boot/docs/2.5.9/reference/html/using.html#using.build-systems.starters在此链接中可以查看其他场景启动器
需要说明的是,SpringBoot官方没有对所有场景开发提供了启动器。例如Mybatis,但是Mybatis团队主动与SpirngBoot框架进行了整合,实现了自己的依赖启动器。例如mybatis-spring-boot-stater。引用第三方依赖启动器时要指定版本号。
-
SpringBoot的自动配置
SpringBoot是怎么自动配置的 配置了哪些?
根据主启动类的@SpringBootApplication解决问题
@SpringBootApplication public class ReviewApplication { public static void main(String[] args) { SpringApplication.run(ReviewApplication.class, args); } }
Ctrl+鼠标左键@SpringBootApplication进入发现@SpringBootApplication是一个组合注解
@Target(ElementType.TYPE) //注解可以标注的地方 @Retention(RetentionPolicy.RUNTIME) //注解生命周期 @Documented //注解可以记录在javdoc中 @Inherited //表示可以被子类继承注解 -----------------------------下方为重点---------------------------- @SpringBootConfiguration //标注类为配置类 (内部被@Configuration标注) @EnableAutoConfiguration//开启自动配置 @ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class), @Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) }) //包扫描 public @interface SpringBootApplication { 。。。。。。。 }
1.查看一下开启自动配置的注解@EnableAutoConfiguration
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited --------------------------------------------- @AutoConfigurationPackage //会把@SpringBootApplication注解标注的类所在包的所有组件进行注册 @Import(AutoConfigurationImportSelector.class) //导入AutoConfigurationImportSelector组件 public @interface EnableAutoConfiguration { 。。。。。。。。 }
1.1查看@AutoConfigurationPackage注解
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
------------------------------------------------------------
@Import(AutoConfigurationPackages.Registrar.class) //导入组件
public @interface AutoConfigurationPackage {
}
1.1.1进入Registrar.class中
static class Registrar implements ImportBeanDefinitionRegistrar, DeterminableImports {
@Override
public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
//这里是对SpringBoot主启动类所在包的所有组件进行注册
register(registry, new PackageImports(metadata).getPackageNames().toArray(new String[0]));
}
@Override
public Set<Object> determineImports(AnnotationMetadata metadata) {
return Collections.singleton(new PackageImports(metadata));
}
}
1.2.1进入Import注解中的AutoConfigurationImportSelector类中
在这个类中有一个方法,表示了要导入哪些组件
public String[] selectImports(AnnotationMetadata annotationMetadata) {
//判断有没有开启@EnableAutoConfiguration(默认开启)
if (!isEnabled(annotationMetadata)) {
return NO_IMPORTS;
}
//在这里面会加载自动配置类
//在这里会一步步到AutoConfigurationMetadataLoader类
//在AutoConfigurationMetadataLoader类中标注了扫描自动配置配置文件的路径
AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(annotationMetadata);
return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
}
这个就是配置文件中的内容
内容命名规则:类的全限定名.条件=值。