使用Spring Boot實現模組化
SpringBoot為模組化提供了非常直接簡單的組合方式,可以說完全替代OSGI或其他模組外掛技術。
什麼是Spring Boot中的模組?
本文意義上的“模組”是一組載入到應用程式上下文中的Spring元件。
模組可以是業務模組,為應用程式提供一些業務服務,或者為幾個其他模組或整個應用程式提供跨領域關注的技術模組。
建立模組的幾種辦法
Spring模組的基礎是一個@Configuration註釋,這是一種Spring的Java配置特性,可以用來標註在你的模組配置類中,配合@Configuration有幾種更細粒度的方式:
(1)@ComponentScan
建立模組的最簡單方法是使用@ComponentScan註釋:
@Configuration
@ComponentScan(basePackages = "io.reflectoring.booking")
public class BookingModuleConfiguration {
}
如果這個配置類由importing 機制(稍後解釋)匯入的一個,它將檢視包io.reflectoring.booking中的所有類,如果使用了Spring的構造型註釋中任何一個註釋,這些類的例項將被載入到Spring的應用上下文中。
只要你總是希望將包及其子包的所有類載入到Spring應用上下文中,那麼使用這種方式就可以了。如果你需要更多控制載入內容,請繼續。。
(2)@Bean 定義
Spring的Java配置功能還有一個@Bean註釋,用於建立載入bean的例項到Spring應用上下文中:
@Configuration public class BookingModuleConfiguration { @Bean public BookingService bookingService(){ return new BookingService(); } // potentially more @Bean definitions ... } <p class="indent"> |
匯入此配置類時,BookingService例項將被建立並插入Spring的應用上下文中。
使用這種方式進行模組的建立就可以更清楚地瞭解實際載入的bean,因為你只需要檢視一個地方(配置類),更方便 ,這種辦法與使用@ComponentScan地方相比,後者需要你檢視包中所有類的構造型註釋,看看是什麼構造型,符合條件才能被載入。
(3)@Conditional 註釋
如果你需要對哪些元件應該載入到Spring應用上下文中要進行更細粒度的控制,則可以使用Spring Boot的@Conditional...註釋:
@Configuration @ConditionalOnProperty(name = "io.reflectoring.security.enabled", havingValue = "true", matchIfMissing = true) public class SecurityModuleConfiguration { // @Bean definitions ... } <p class="indent"> |
在使用這個模組時,必須在application配置檔案中設定屬性io.reflectoring.security.enabled為true才能使用這個模組。(見後面使用模組)
還可以使用其他@Conditional...註釋來定義載入模組的條件。有一個依賴條件,具體取決於JVM的版本以及某個類是否存在於類路徑中或某個bean是否存在於Spring應用上下文中。
如果你曾經問過自己Spring Boot如何神奇地將應用程式所需的bean載入到應用程式上下文中,原理就在於使用了這個註釋@Conditional,Spring Boot本身大量使用@Conditional註釋。
以上三種辦法是建立一個模組的方式,那麼如何使用這些模組呢?也有幾種方式可選,注意,要分清模組建立和模組使用兩個大的邊界。
使用模組的幾種辦法
建立模組後,我們需要將其匯入到SpringBoot應用程式中,有下面幾種辦法:
(1)@Import
最直接的方法是使用@Import註釋:
@SpringBootApplication @Import(BookingModuleConfiguration.class) public class ModularApplication { // ... } <p class="indent"> |
這將匯入BookingModuleConfiguration類及其隨附的所有bean - 無論它們是由宣告@ComponentScan還是@Bean註釋。
(2)@Enable... 註釋
Spring Boot帶有一組註釋,每個註釋都自己匯入某個模組。一個例子是@EnableScheduling,它匯入排程子系統所需的所有Beans及其@Scheduled註釋,也就是說,如果你在你的應用類中使用了@Scheduled註釋,如果想使得這種排程功能起效,還必須在入口處加入@EnableScheduling,否則就不起效,這也是SpringBoot使用中容易掉的坑,關鍵還是沒有了解Spring的模組機制:
@SpringBootApplication @EnableScheduling public class SpringbatchApplication { public static void main(String[] args) { SpringApplication.run(SpringbatchApplication.class, args); } } <p class="indent"> |
我們也可以匯入自己的Enable配置:
@SpringBootApplication @EnableBookingModule public class ModularApplication { public static void main(String[] args) { SpringApplication.run(ModularApplication.class, args); } } <p class="indent"> |
上面程式碼中EnableBookingModule不是Spring自己的註釋,而是我們自己的定做的,程式碼如下:
@Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE}) @Documented @Import(BookingModuleConfiguration.class) @Configuration public @interface EnableBookingModule { } <p class="indent"> |
該@EnableBookingModule註釋實際上只是包裝了@Import,首先匯入我們的BookingModuleConfiguration,如果我們有一個模組是由多個配置類組成,這種辦法是一種將這些配置類聚合到單個模組中的方便且富有表現力的方法。
(3)自動配置Auto-Configuration
如果我們想自動載入模組而不是將之前那樣在原始碼中匯入指定的硬連線hard-wiring,我們可以使用Spring Boot的自動配置功能,也就是不再原始碼中使用註釋,而是使用配置檔案。
請在模組所在專案下(注意,不是模組使用的專案)建立檔案META-INF/spring.factories,執行時需要放入classpath類路徑中 ,在該檔案中寫入:
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ io.reflectoring.security.SecurityModuleConfiguration <p class="indent"> |
多個配置:
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ com.mycorp.libx.autoconfigure.LibXAutoConfiguration,\ com.mycorp.libx.autoconfigure.LibXWebAutoConfiguration <p class="indent"> |
該模組的使用者所在Springboot專案啟動時會將SecurityModuleConfiguration類的所有bean匯入到Spring應用上下文中。
要在SpringBoot中使用這個SecurityModuleConfiguration,還需要在模組使用的專案中在application.yml中定義:
io: reflectoring: security: enabled: true <p class="indent"> |
這裡將io.reflectoring.security.enabled設定true,是對應前面該模組建立時使用@Conditional註釋時有一個條件:
@ConditionalOnProperty(name = "io.reflectoring.security.enabled", havingValue = "true", matchIfMissing = true) <p class="indent"> |
使用模組的策略
前面介紹了在Spring Boot應用程式中使用模組的幾個辦法,但是我們什麼時候在什麼情況下選擇哪一個呢?
(1)業務模組使用@Import
對於包含業務邏輯的模組 - 比如上面的BookingModuleConfiguration - 在大多數情況下使用@Import,使用帶註釋的靜態匯入應該足夠了。通常那些沒有載入業務模組也是沒有意義的,因此我們不需要對它們的載入條件進行任何控制。
(2)技術模組使用自動配置
另一方面,技術性的模組 - 如安全SecurityModuleConfiguration - 這些技術通常會提供一些跨域的切面關注(類似AOP),例如日誌記錄,異常處理,授權或監視功能,這些功能在開發和執行時需求不一樣,在開發過程中,可能根本不需要這些功能,因此我們希望有一種方法來禁用它們。
我們不希望使用@Import靜態地匯入每個技術模組,因為它們不應該對我們的程式碼產生任何影響。
因此,使用技術模組的最佳選擇是自動配置功能。模組在後臺靜默載入,我們可以使用在程式碼之外配置屬性中影響它們。
本文案例:github
相關文章
- 使用Spring Boot的Configuration和ArchUnit實現元件模組化和清晰邊界 - reflectoringSpring Boot元件
- Spring-boot模組化程式設計Springboot程式設計
- 使用 Spring Boot 構建可重用的模擬模組Spring Boot
- spring boot(三)web模組Spring BootWeb
- 使用Spring Boot實現事務管理Spring Boot
- 使用Spring Boot實現的GraphQL示例Spring Boot
- Android實現模組 api 化AndroidAPI
- 如何實現css模組化CSS
- spring boot(四)資料訪問模組Spring Boot
- 使用Spring Boot實現訊息佇列Spring Boot佇列
- 使用Spring Boot實現分散式事務Spring Boot分散式
- 使用Spring Boot實現Redis事務 | VinsguruSpring BootRedis
- 使用Spring Boot和Kafka Streams實現CQRSSpring BootKafka
- 真棒:使用Java 11實現應用的模組化Java
- 在Spring Boot實現國際化的案例Spring Boot
- 模組化實現的好處
- Spring Boot 模組工程(透過 Maven Archetype)建立Spring BootMaven
- Spring Boot + MyBatis 多模組專案搭建教程Spring BootMyBatis
- 使用Spring Boot實現檔案上傳功能Spring Boot
- 使用Vue+Spring Boot實現Excel上傳VueSpring BootExcel
- Nginx使用Lua模組實現WAFNginx
- Spring Boot實現Web SocketSpring BootWeb
- 一種app模組化實現方案APP
- Java模組化的國際化實現- GunnarJava
- 使用 Spring Boot 3.2 和 CRaC 實現更快啟動Spring Boot
- 使用Spring Boot實現資料庫整合配置案例Spring Boot資料庫
- spring boot使用Jedis整合Redis實現快取(AOP)Spring BootRedis快取
- 使用Spring Boot實現動態健康檢查HealthChecksSpring Boot
- iOS使用觀察者模式實現推送訊息模組化iOS模式
- Spring Boot + Maven 多模組專案開發詳解Spring BootMaven
- Spring Boot之驗證模組應用總結2Spring Boot
- webpack是如何實現前端模組化的Web前端
- Spring Boot中實現Thymeleaf通知Spring Boot
- Spring boot webflux 中實現 RequestContextHolderSpring BootWebUXContext
- 【流式傳輸】使用Spring Boot實現ChatGpt流式傳輸Spring BootChatGPT
- 使用Spring Boot, Istio和Cert Manager實現Kubernetes的HTTPSSpring BootHTTP
- Spring Boot系列之使用@Scheduled實現定時任務Spring Boot
- Spring Boot 使用 JSR303 實現引數驗證Spring BootJS