<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
SpringBoot的預定優於設定主要體現在以下幾個方面:
maven的目錄結構:
resources
目錄下target
目錄下jar
格式組態檔預設為application.yml
或application.yaml
或application.properties
預設通過 spring.profiles.active 屬性來決定執行環境時的組態檔。
相對於傳統的Spring專案的繁瑣設定,SpringBoot專案只需要使用一個@SpringBootApplication
註解就可以成功執行,哪有什麼歲月靜好,只不過是有人在替我們負重前行。讓我們來看一看在@SpringBootApplication
註解的背後SpringBoot為我們做了哪些事情。
可以看到@SpringBootApplication
是一個組合註解,上面四個不用看,因為是定義一個註解必須的,關鍵在於下面的@SpringBootConfiguration``@EnableAutoConfiguration``@ComponentScan
三個註解。也就是說我們不用@SpringBootApplication
,使用下這三個註解也可以成功執行一個SpringBoot應用。
@SpringBootConfiguration註解
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Configuration public @interface SpringBootConfiguration { }
點進原始碼可以發現,它實際上就是一個@Configuration
註解,@Configuration
大家應該都很熟悉了,加上這個註解後當前類就會被Spring所管理 。
@ComponentScan註解
這個註解用於定義Spring的掃描路徑,等價於<context:component-scan>
,如果沒有設定掃描路徑,那麼SpringBoot會預設掃描當前類的包及其子包中所有標註了需要被管理的類。
@EnableAutoConfiguration
這個註解才是SpringBoot自動裝配的關鍵,這也是一個組合註解
@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 {}; }
@AutoConfigurationPackage
其實也是一個@Import
註解
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited @Import(AutoConfigurationPackages.Registrar.class) public @interface AutoConfigurationPackage { }
@Import註解
在@Configuration
標註的Class上可以使用@Import
引入其它的設定類,其實它還可以引入org.springframework.context.annotation.ImportSelector
實現類。ImportSelector
介面只定義了一個selectImports()
,用於指定需要註冊為bean的Class名稱。當在@Configuration
標註的Class上使用@Import
引入了一個ImportSelector
實現類後,會把實現類中返回的Class名稱都定義為bean。
@EnableAutoConfiguration
中@Import
主要就是為了匯入一個AutoConfigurationImportSelector
,下面我們分析一下這個類:
AutoConfigurationImportSelector類
AutoConfigurationImportSelect
類實現了ImportSelector
介面,所以我們清楚只需關注selectImports()
方法的返回結果即可:
@Override public String[] selectImports(AnnotationMetadata annotationMetadata) { if (!isEnabled(annotationMetadata)) { return NO_IMPORTS; } AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader .loadMetadata(this.beanClassLoader); AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(autoConfigurationMetadata, annotationMetadata); return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations()); }
該方法返回的是要註冊到IOC容器中的物件的型別的全路徑名稱的字串陣列,所以我們要分析一下這個陣列是從哪裡來的?
進入到getAutoConfigurationEntry
方法中:
protected AutoConfigurationEntry getAutoConfigurationEntry(AutoConfigurationMetadata autoConfigurationMetadata, AnnotationMetadata annotationMetadata) { if (!isEnabled(annotationMetadata)) { return EMPTY_ENTRY; } // 獲取註解的屬性資訊 AnnotationAttributes attributes = getAttributes(annotationMetadata); // 獲取候選設定 List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes); configurations = removeDuplicates(configurations); Set<String> exclusions = getExclusions(annotationMetadata, attributes); checkExcludedClasses(configurations, exclusions); configurations.removeAll(exclusions); configurations = filter(configurations, autoConfigurationMetadata); fireAutoConfigurationImportEvents(configurations, exclusions); return new AutoConfigurationEntry(configurations, exclusions); }
通過DEBUG可以看到,在getCandidateConfigurations
方法中獲取到了很多java類全路徑
進入getCandidateConfigurations方法,可以看到有一個斷言:如果configurations為空的話,會提示No auto configuration classes found in META-INF/spring.factories. If you are using a custom packaging, make sure that file is correct(在META-INF/spring.factories中找不到自動設定類。如果您使用的是自定義打包,請確保該檔案正確無誤)
由此我們可以推測:自動設定的類名陣列在META-INF/spring.factories
檔案中,並且我們可以通過在正確的路徑下面新增這個檔案來自定義包來適配SpringBoot
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) { List<String> configurations = SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(), getBeanClassLoader()); Assert.notEmpty(configurations, "No auto configuration classes found in META-INF/spring.factories. If you " + "are using a custom packaging, make sure that file is correct."); return configurations; }
進入這個檔案可以看到,這裡設定了大量的需要自動裝配的類,當我們啟動Springboot專案的時候,SpringBoot會掃描所有jar包下面的META-INF/spring.factories
檔案,並根據key進行讀取,在經過一系列的操作來完成自動裝配。
需要注意的是:上圖中的 spring.factories
檔案是在 spring-boot-autoconfigure
包下面,這個包記錄了官方提供的 stater 中幾乎所有需要的自動裝配類,所以並不是每一個官方的 starter 下都會有 spring.factories
檔案。
@AutoConfigurationPackage註解
@AutoConfigurationPackage註解的主要作用就是將主程式類所在包及所有子包下的元件到掃描到spring容器中。
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited @Import(AutoConfigurationPackages.Registrar.class) public @interface AutoConfigurationPackage { }
這個註解實際上是匯入了AutoConfigurationPackages
的一個內部類Registrar
,這個類的作用就是讀取到最外層@SpringBootApplication
註解中設定的掃描路徑(沒有設定預設當前所在包),將該路徑下所有檔案掃描,並分析註冊bean。
static class Registrar implements ImportBeanDefinitionRegistrar, DeterminableImports { @Override public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) { register(registry, new PackageImport(metadata).getPackageName()); } @Override public Set<Object> determineImports(AnnotationMetadata metadata) { return Collections.singleton(new PackageImport(metadata)); } }
上面提到在自己的包中新增META-INF/spring.factories
檔案就可以適配SpringBoot實現自動設定,這其實是一種SPI的思想。
SPI,Service Provider Interface。即:介面服務的提供者。就是說我們應該面向介面(抽象)程式設計,而不是面向具體的實現來程式設計,這樣一旦我們需要切換到當前介面的其他實現就無需修改程式碼。
starter的命名規範:
官方的starter命名格式為spring-boot-starter-{xxx}
,例如:spring-boot-starter-web
等
自定義starter命名格式一般為{xxx}-spring-boot-starter
,例如mybatis的mybatis-spring-boot-starter
1) 新建一個springboot專案myself-spring-boot-starter
2) 新建自己的業務類
public class MyselfService { private String myself; // ……省略 getter setter public String doBusiness(Object obj){ return myself+obj.toString(); } }
3)業務需要的一些屬性值
@ConfigurationProperties("myself") public class MysefProperties { private String myself; // ……省略 getter setter }
4)新建自動裝配類,把自己的業務交給Spring管理
@Configuration @EnableConfigurationProperties(MysefProperties.class) public class MyselfAutoConfiguration { @Autowired MysefProperties mysefProperties; @Bean @ConditionalOnMissingBean(MyselfService.class) public MyselfService myselfService(){ MyselfService myselfService = new MyselfService(); myselfService.setMyself(mysefProperties.getMyself()); return myselfService; } }
5)在resources/META-INF下新建spring.factories,設定starter中設定類的位置
org.springframework.boot.autoconfigure.EnableAutoConfiguration=
com.yy.autoconfigure.MyselfAutoConfiguration
6)mvn install將自己的包打到自己倉庫中,在另外的專案直接參照即可
7)測試
mybatis-plus-boot-starter
我們可以學習一下其他第三方的成熟的starter,會發現其實套路是很相似的
到此這篇關於SpringBoot詳細分析自動裝配原理並實現starter的文章就介紹到這了,更多相關SpringBoot自動裝配原理內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45