javascript
java校验框架源码解析_Spring Boot原理剖析和源码分析
Spring Boot原理剖析和源碼分析
依賴管理
問題一:為什么導入dependency時不需要指定版本?
spring-boot-starter-parent依賴
org.springframework.boot
spring-boot-starter-parent
2.3.0.RELEASE
上述代碼中,將spring-boot-starter-parent依賴作為Spring Boot項目的統一父項目依賴管理,并將項目版本號統一為2.3.0.RELEASE,該版本號根據實際開發需求可以修改。
org.springframework.boot
spring-boot-dependencies
2.3.0.RELEASE
繼續查看spring-boot-dependencies底層源文件
5.15.12
2.7.7
1.9.80
2.12.0
1.9.5
3.16.1
4.0.6
4.0.2
2.1.4
3.1.0
1.10.10
2.8.2
4.6.1
1.5.1
1.14
......
從spring-boot-dependenices底層源文件可以看出,該文件通過標簽對一些常用技術框架的依賴文件進行了統一版本號管理,如activemq、spring、tomcat等,都有與Spring Boot2.3.0.RELEASE版本相匹配的版本,這也是pom.xml引入依賴文件不需要標注依賴文件版本號的原因。
問題二:spring-boot-starter-parent伏以來啟動器的主要作用是進行版本統一管理,那么項目運行依賴的jar包是從何而來?
spring-boot-starter-web
org.springframework.boot
spring-boot-starter
2.1.7.RELEASE
compile
org.springframework.boot
spring-boot-starter-json
2.1.7.RELEASE
compile
org.springframework.boot
spring-boot-starter-tomcat
2.1.7.RELEASE
compile
org.hibernate.validator
hibernate-validator
6.0.17.Final
compile
org.springframework
spring-web
5.1.9.RELEASE
compile
org.springframework
spring-webmvc
5.1.9.RELEASE
compile
從上述可以看出,spring-boot-starter-web依賴啟動器的主要作用是提供web開發場景所需要的底層所有依賴。
版本由spring-boot-starter-parent統一進行管理。
image-20200526100443828.png
Spring Boot官網提供了部分場景的依賴啟動器,這些依賴適用與不同的開發場景,適用時直接在pom.xml中導入即可。
但是Spring Boot官網并不是針對所有的場景的開發技術框架都提供了依賴啟動器,如mybatis、druid等,但是為了充分利用Spring Boot框架的優勢,mybatis、druid等技術框架團隊主動與Spring Boot框架進行了整合,實現了各自的依賴啟動器。mybatis-spring-boot-starter、druid-spring-boot-starter。在需要的時候直接在pom.xml文件中導入即可,但是需要自己管理版本號。
自動配置(啟動流程)
概念:能夠在我們添加jar包依賴時,自動為我們進行配置一下配置,我們可以不需要配置或者少量配置就能運行編寫的項目。
問題:Spring Boot到底是如何進行自動配置的,都把那些組件進行了自動配置?
Spring Boot 應用啟動的入口是@SpringBootApplication注解標注類的main方法,
@SpringBootApplication能夠掃描Spring組件并且自動配置Spring Boot
@SpringBootApplication
public class RegistryApplication {
public static void main(String[] args) {
SpringApplication.run(RegistryApplication.class);
}
}
@SpringBootApplication注解類
// 注解的適用范圍:類、接口、枚舉
@Target({ElementType.TYPE})
// 注解的生命周期:運行時
@Retention(RetentionPolicy.RUNTIME)
// 標明注解可標注在javadoc中
@Documented
// 標明注解可以被子類繼承
@Inherited
// 標明該類為配置類
@SpringBootConfiguration
// 啟動自動配置功能
@EnableAutoConfiguration
// 包掃描器
@ComponentScan(
excludeFilters = {@Filter(
type = FilterType.CUSTOM,
classes = {TypeExcludeFilter.class}
), @Filter(
type = FilterType.CUSTOM,
classes = {AutoConfigurationExcludeFilter.class}
)}
)
public @interface SpringBootApplication {
@AliasFor(
annotation = EnableAutoConfiguration.class
)
Class>[] exclude() default {};
@AliasFor(
annotation = EnableAutoConfiguration.class
)
String[] excludeName() default {};
@AliasFor(
annotation = ComponentScan.class,
attribute = "basePackages"
)
String[] scanBasePackages() default {};
@AliasFor(
annotation = ComponentScan.class,
attribute = "basePackageClasses"
)
Class>[] scanBasePackageClasses() default {};
}
從上面可以看出,@SpringBootApplication注解主要由@SpringBootConfiguration、@EnableAutoConfiguration、@ComponentScan這三個核心注解組成。
@SpringBootConfiguration注解
@SpringBootConfiguration注解表示為Spring Boot配置類
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
// 配置到IOC容器
@Configuration
public @interface SpringBootConfiguration {
}
從上述可以看出,@SpringBootConfiguration注解類主要注解為@Configuration注解,該注解由Spring框架提供,表示當前類為一個配置類,并且可以被組件掃描器掃描。
@EnableAutoConfiguration注解
@EnableAutoConfiguration注解表示為自動配置類,該注解是Spring Boot最重要的注解,也是實現自動配置的注解。
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
// 自動配置包
@AutoConfigurationPackage
// 自動配置掃描導入
@Import({AutoConfigurationImportSelector.class})
public @interface EnableAutoConfiguration {
String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";
Class>[] exclude() default {};
String[] excludeName() default {};
}
從源碼可以發現,@EnableAutoConfiguration注解為一個組合注解,其作用就是借助@Import注解導入特定場景需要向IOC注冊的Bean,并且加載到IOC容器。@AutoConfigurationPackage就是借助@Import來搜集所有符合自動配置條件的Bean定義,并且加載到IOC容器中。
(1)@AutoConfigurationPackage
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
// 導入Registrar中注冊的組件
@Import({Registrar.class})
public @interface AutoConfigurationPackage {
}
從源碼可以看出,@AutoConfigurationPackage注解的功能由@Import注解實現,它是Spring框架底層注解,它的作用就是給容器導入某個組件類
static class Registrar implements ImportBeanDefinitionRegistrar, DeterminableImports {
Registrar() {
}
public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
// 將主程序類所在的包以及所有子包下的組件掃描到Spring容器
AutoConfigurationPackages.register(registry, (new AutoConfigurationPackages.PackageImport(metadata)).getPackageName());
}
public Set determineImports(AnnotationMetadata metadata) {
return Collections.singleton(new AutoConfigurationPackages.PackageImport(metadata));
}
}
從上述可以看出,@AutoConfigurationPackage注解的主要作用就是將主程序類所在的包以及所有子包下的組件加載到IOC容器中。
因此:在定義項目包目錄時,要求定義的包結構必須規范,項目主程序啟動類要放在最外層的根目錄位置,然后在根目錄的位置內部建立子包和類進行業務開發,這樣才能保證定義的類才能被組件掃描器掃描。
(2)@Import({AutoConfigurationImportSelector.class})
將 AutoConfigurationImportSelector 類導入到Spring容器中。AutoConfigurationImportSelector 可以幫助Spring容器將所有符合條件的@Configuration配置都加載到Spring Boot創建并使用的IOC容器(ApplicationContext)中。
public String[] selectImports(AnnotationMetadata annotationMetadata) {
if (!this.isEnabled(annotationMetadata)) {
return NO_IMPORTS;
} else {
// 獲取自動配置的元數據,需要傳入beanClassLoader這個類加載器
AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader.loadMetadata(this.beanClassLoader);
AutoConfigurationImportSelector.AutoConfigurationEntry autoConfigurationEntry = this.getAutoConfigurationEntry(autoConfigurationMetadata, annotationMetadata);
return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
}
}
protected AutoConfigurationImportSelector.AutoConfigurationEntry getAutoConfigurationEntry(AutoConfigurationMetadata autoConfigurationMetadata, AnnotationMetadata annotationMetadata) {
if (!this.isEnabled(annotationMetadata)) {
return EMPTY_ENTRY;
} else {
AnnotationAttributes attributes = this.getAttributes(annotationMetadata);
// 從META-INF/spring.factories配置文件中將對于的自動配置類獲取到
List configurations = this.getCandidateConfigurations(annotationMetadata, attributes);
configurations = this.removeDuplicates(configurations);
Set exclusions = this.getExclusions(annotationMetadata, attributes);
this.checkExcludedClasses(configurations, exclusions);
configurations.removeAll(exclusions);
configurations = this.filter(configurations, autoConfigurationMetadata);
this.fireAutoConfigurationImportEvents(configurations, exclusions);
return new AutoConfigurationImportSelector.AutoConfigurationEntry(configurations, exclusions);
}
}
@EnableAutoConfiguration注解就是從classpath中搜尋META-INF/spring.factories配置文件,并將其org.springframework.boot.autoconfigure.EnableAutoConfiguration對于的配置通過反射實例化對應的標注了@Configuration的JavaConfig配置類,并且加載到IOC容器中。
以web項目為例,在項目中加入了web環境依賴啟動器,對應的org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration自動配置就會生效,打開自動配置就會發現,在配置類中通過全注解的方式對 Spring MVC 運行環境所需要環境進行了默認配置,包括前綴、后綴、試圖解析器、MVC校驗器等。
總結
Spring Boot底層實現自動配置的步驟:
spring boot 應用啟動
@SpringBootApplication起作用
@EnableAutoConfiguration
@AutoConfigurationPackage
這個注解主要作用就是@Import({Registrar.class}),它通過Registrar類導入容器中,而Registrar的作用就是將掃描主配置類的包以及子包,并將對應的組件導入IOC容器中。
@Import({AutoConfigurationImportSelector.class})
它將 AutoConfigurationImportSelector 類導入容器中,AutoConfigurationImportSelector 類的作用是通過selectImports()方法執行的過程中,會使用內部工具類SpringFactoriesLoader,查找classpath上所有的jar包中的META-INF/spring.factories進行加載,實現將配置類信息交給Spring Factory加載器進行一系列的容器創建過程。
(3)@ComponentScan
@ComponentScan注解具體掃描包的路徑,由Spring Boot主程序所在包的位置決定。在掃描的過程中由@AutoConfigurationPackage注解進行解析,從而得到Spring Boot主程序類所在包的具體位置
《新程序員》:云原生和全面數字化實踐50位技術專家共同創作,文字、視頻、音頻交互閱讀總結
以上是生活随笔為你收集整理的java校验框架源码解析_Spring Boot原理剖析和源码分析的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java图像分类源码_在Android设
- 下一篇: java常用注解及功能_SpringBo