一起玩轉微服務(12)——揭密starter
介紹
Spring Boot的starter主要用來簡化依賴用的,對於企業級開發中的與第三方的整合,可以通過一段簡單的配置來完成,這樣開發人員無需再對包依賴的問題頭疼。Spring Boot為我們提供了簡化企業級開發的絕大多數場景的starter pom,只需要指定需要配置的starter,Spring Boot會自動為我們提供配置好的bean。
通常流程
通常我們要搭建一個基於Spring的Web應用,我們需要做以下一些工作:
pom檔案中引入相關jar包,包括spring、springmvc、redis、mybaits、log4j、mysql-connector-java 等等相關jar …
配置web.xml,Listener配置、Filter配置、Servlet配置、log4j配置、error配置 …
配置資料庫連線、配置spring事務
配置檢視解析器
開啟註解、自動掃描功能
配置完成後部署tomcat、啟動除錯
……
花在搭建一個初始專案,可能一個小時就過去了或者半天就過了,但是用了SpringBoot之後一切都會變得非常便捷。
常用的starter
Spring Boot常用的starter(啟動器)包括:
- Spring-boot-starter-logging :使用 Spring Boot 預設的日誌框架 Logback。
- Spring-boot-starter-log4j :新增 Log4j 的支援。
- Spring-boot-starter-web :支援 Web 應用開發,包含 Tomcat 和 Spring-mvc。
- Spring-boot-starter-tomcat :使用 Spring Boot 預設的 Tomcat 作為應用伺服器。
- Spring-boot-starter-jetty :使用 Jetty 而不是預設的 Tomcat 作為應用伺服器。
- Spring-boot-starter-test :包含常用的測試所需的依賴,如 Junit、Hamcrest、Mockito 和 Spring-test 等。
- Spring-boot-starter-AOP :包含 Spring-AOP 和 AspectJ 來支援面向切面程式設計(AOP)。
- Spring-boot-starter-security :包含 Spring-security。
- Spring-boot-starter-jdbc :支援使用 JDBC 訪問資料庫。
- Spring-boot-starter-redis :支援使用 Redis。
- Spring-boot-starter-data-mongodb :包含 Spring-data-mongodb 來支援 MongoDB。
- Spring-boot-starter-data-jpa :包含 Spring-data-jpa、Spring-orm 和 Hibernate 來支援 JPA。
- Spring-boot-starter-amqp :通過 Spring-rabbit 支援 AMQP。
- Spring-boot-starter-actuator : 新增適用於生產環境的功能,如效能指標和監測等功能。
當然,如果有必要,也可以定製自己的starter。
起步依賴
在我們的pom檔案裡面引入以下jar:
spring-boot-starter-web包自動幫我們引入了web模組開發需要的相關jar包。
mybatis-spring-boot-starter幫我們引入了dao開發相關的jar包。 spring-boot-starter-xxx是官方提供的starter,xxx-spring-boot-starter是第三方提供的starter。
截圖看一下我們的mybatis-spring-boot-starter
可以看出mybatis-spring-boot-starter並沒有任何原始碼,只有一個pom檔案,它的作用就是幫我們引入其它jar。
得益於starter的作用,使用SpringBoot確實方便,但對剛剛上手SpringBoot的人來說,可能只知道配置屬性是在application.xml或application.yml中新增,但他們各自的屬性都有哪些,具體怎麼配置,卻無從下手。這裡先解決SpringBoot-starter中各屬性的配置問題。
Mybatis的配置是怎麼生效的?檢視示例工程的pom依賴:
注意到mybatis-spring-boot-starter幫我們自動依賴了Mybatis所需jar包,其中有一個負責自動配置的mybatis-spring-boot-autoconfigure.jar,緊接著開啟此jar,如下:
META-INF/spring-configuration-metadata.json中便是Mybatis在SpringBoot中的所有配置屬性和介紹。
SpringBoot-starter自動配置bean
現在已得知jar包是怎麼樣自動依賴進來,以及他們的配置屬性,那麼接下來該考慮Mybatis所需的bean(如必需的sqlSessionFactory、sqlSessionTemplate等)是如何被自動載入的?
理所應當地,我們繼續去檢視mybatis-spring-boot-autoconfigure.jar,注意到裡面有一個自動配置的類MybatisAutoConfiguration:
(1)@Configuration:被掛上@Configuration註解,表明它是一個配置類,作用等同於xml配置,裡面有被@Bean註解的方法,也等同於xml配置的各種。
(2)@ConditionalOnClass/@ConditionalOnBean:自動配置條件註解,用於在某一部分配置中,將另一模組部分的配置自動載入進來,因為隨著系統越來越大,配置內容越來越多,我們應當將Mybatis的配置放在一處,將log4j的配置放在一處,將SpringBoot自身的配置放在一處,當他們需要互相依賴時,可通過這類註解進行自動配置,如下:
@ConditionalOnClass @ConditionalOnMissingClass @ConditionalOnBean @ConditionalOnMissingBean @ConditionalOnProperty @ConditionalOnResource @ConditionalOnWebApplication @ConditionalOnNotWebApplication @ConditionalOnExpression @AutoConfigureAfter @AutoConfigureBefore @AutoConfigureOrder(指定順序)
(3)@EnableConfigurationProperties:啟用對@ConfigurationProperties註解的bean的支援,這裡對應了配置屬性類MybatisProperties,它裡面定義了Mybatis的所有配置。
(4)@AutoConfigureAfter:應在其他指定的自動配置類之後應用自動配置。即org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration被自動配置後,才會接著自動配置MybatisAutoConfiguration。這裡也解釋了為什麼我們在application.xml中只配置了資料來源,而沒有配置Mybatis,但是Mybatis可以正常查庫的原因,就是因為它們配置之間的依賴關係。
到這裡,差不多明白了starter自動配置bean的方式,但是如若再去深究,各種starter的bean是如何被自動載入的,猜想會不會是專案啟動後,SpringBoot自動掃描裡面所有的jar包,再去掃描所有的類,從而將各個bean放置IOC容器中。從結果來看,肯定是SpringBoot在啟動時確確實實地自動載入了資料來源和Mybatis相關的bean,不然他們無法正常工作。
回想在我們啟動示例工程時,SpringBoot會自動掃描啟動類所在包下的所有類,而如果還去掃描所有的jar包的話,又是具體怎麼做到的?不妨從入口類除錯一把,在SpringApplication.run(DemoApplication.class, args)打斷點,一直追蹤到getSpringFactoriesInstances這塊:
檢視SpringFactoriesLoader.loadFactoryNames的方法註釋:
使用給定的類載入器從META-INF / spring.factories載入給定型別的工廠實現的完全限定類名。
這裡的spring.factories剛好也存在於mybatis-spring-boot-autoconfigure.jar中,
繼續除錯,進入SpringFactoriesLoader.loadFactoryNames,
這裡用類載入器得到工程中所有jar包中的META-INF/spring.factories檔案資源,進而通過此檔案得到了一些包括自動配置相關的類的集合,有各種工廠類、監聽器、處理器、過濾器、初始化器等等,如下:
最後的org.springframework.boot.autoconfigure.EnableAutoConfiguration集合中當然包括了org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration和org.mybatis.spring.boot.autoconfigure.MybatisAutoConfiguration。接著必然是將例項化的各個bean放進IOC容器中。
至此我們便明白了SpringBoot是如何自動配置starter裡面的bean的。
&n