整理自:
博客園:龍四丶:SpringBoot系列java
SpringBoot 中運用了大量的 Spring 註解,其註解大體分爲這幾類:web
模式註解都標註了 @Component 註解,屬於 @Component 的派生註解,@ComponentScan 會掃描標註 @Component 及其派生註解的類,並將這些類加入到 Spring 容器中;@Enable 模塊註解中經過 @Import 導入配置類,在這些配置類中加載 @Enable 模塊須要的組件。redis
模式註解是一種用於聲明在應用中扮演「組件」角色的註解。如 Spring 中的 @Repository 是用於扮演倉儲角色的模式註解,用來管理和存儲某種領域對象。還有如@Component 是通用組件模式、@Service 是服務模式、@Configuration 是配置模式等。其中@Component 做爲一種由 Spring 容器託管的通用模式組件,任何被 @Component 標註的組件均爲組件掃描的候選對象。相似地,凡是被 @Component 標註的註解,如@Service ,當任何組件標註它時,也被視做組件掃描的候選對象。spring
@ComponentScan(basePackages = "com.loong.spring.boot") public class SpringConfiguration { }
註解的形式,依靠 basePackages 屬性指定掃描範圍。Spring 在啓動時,會在某個生命週期內建立全部的配置類註解解析器,而 @ComponentScan 的處理器爲 ComponentScanAnnotationParser。數據庫
所謂「模塊」是指具有相同領域的功能組件集合,組合所造成的一個獨立的單元,好比 Web MVC 模塊、AspectJ代理模塊、Caching(緩存)模塊、JMX(Java 管理擴展)模塊、Async(異步處理)模塊等。編程
Spring Boot和Spring Cloud版本中都一直被使用,這種模塊化的註解均以 @Enable 做爲前綴,以下所示:設計模式
框架實現 | @Enable註解模塊 | 激活模塊 |
---|---|---|
Spring Framework | @EnableWebMvc | Web Mvc 模塊 |
/ | @EnableTransactionManagement | 事物管理模塊 |
/ | @EnableWebFlux | Web Flux 模塊 |
Spring Boot | @EnableAutoConfiguration | 自動裝配模塊 |
/ | @EnableConfigurationProperties | 配置屬性綁定模塊 |
/ | @EnableOAuth2Sso | OAuth2 單點登錄模塊 |
Spring Cloud | @EnableEurekaServer | Eureka 服務器模塊 |
/ | @EnableFeignClients | Feign 客戶端模塊 |
/ | @EnableZuulProxy | 服務網關 Zuul 模塊 |
/ | @EnableCircuitBreaker | 服務熔斷模塊 |
條件裝配指的是經過一些列操做判斷是否裝配 Bean ,也就是 Bean 裝配的前置判斷。實現方式主要有兩種:@Profile 和 @Conditional。數組
@Conditional(HelloWorldCondition.class) @Component public class HelloWorldConfiguration { public HelloWorldConditionConfiguration (){ System.out.println("HelloWorldConfiguration初始化。。。"); } } public class HelloWorldCondition implements Condition { @Override public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) { // ... return true; } }
經過自定義一個 HelloWorldConfiguration 配置類,再標註 @Conditional 註解導入 HelloWorldCondition類,該類必須實現 Condition 接口,而後重寫 matches 方法,在方法中能夠經過兩個入參來獲取一系列的上下文數據和元數據,最終返回ture或false來斷定該類是否初始化,緩存
二、自動裝配正文在 SpringBoot 時代,經過一個main方法就能夠啓動一個應用,其底層依賴的就是 Spring 幾個註解。從 @SpringBootApplication 註解中的 @EnableAutoConfiguration 註解開始,@EnableAutoConfiguration 屬於 Spring 的 @Enable 模塊註解,在該註解中經過 @Import 導入 AutoConfigurationImportSelector 類,在該類中加載全部以 AutoConfiguration 爲後綴且標註 @Configuration 註解的自動配置類,每一個自動配置類能夠裝配一個外部模塊,如 Web MVC 模塊對應的配置類是 WebMvcAutoConfiguration 。在自動配置類中又有衆多 @Conditional 條件註解,可達到靈活裝配的目的。服務器
Spring Boot 的啓動過程很是簡單,只須要啓動一個 main 方法,項目就能夠運行,就算依賴了諸多外部模塊如:MVC、Redis等,也不須要咱們進行過多的配置。
@SpringBootApplication public class LoongSpringBootApplication { public static void main(String[] args) { SpringApplication.run(LoongSpringBootApplication.class, args); } } //關注的是 @SpringBootApplication 這個註解: @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @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 {}; }
@EnableAutoConfiguration 是實現自動裝配的核心註解,是用來激活自動裝配的,看註解前綴咱們應該知道是Spring @Enable 模塊驅動的設計模式,因此它必然會有 @Import 導入的被 @Configuration 標註的類或實現 ImportSelector 或 ImportBeanDefinitionRegistrar 接口的類。
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited @AutoConfigurationPackage @Import(AutoConfigurationImportSelector.class) public @interface EnableAutoConfiguration { ... }
Spring Boot經過 @AutoConfigurationPackage 註解獲取默認包掃描路徑:
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited @Import(AutoConfigurationPackages.Registrar.class) public @interface AutoConfigurationPackage { }
它是經過 @Import 導入了 AutoConfigurationPackages.Registrar 類,該類實現了 ImportBeanDefinitionRegistrar 接口。
@Configuration @ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET) @ConditionalOnClass({ Servlet.class, DispatcherServlet.class, WebMvcConfigurer.class }) @ConditionalOnMissingBean(WebMvcConfigurationSupport.class) @AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE + 10) @AutoConfigureAfter({ DispatcherServletAutoConfiguration.class, TaskExecutionAutoConfiguration.class, ValidationAutoConfiguration.class }) public class WebMvcAutoConfiguration { ... @Configuration @Import(EnableWebMvcConfiguration.class) @EnableConfigurationProperties({WebMvcProperties.class, ResourceProperties.class}) @Order(0) public static class WebMvcAutoConfigurationAdapter implements WebMvcConfigurer, ResourceLoaderAware { ... @Bean @ConditionalOnBean(View.class) @ConditionalOnMissingBean public BeanNameViewResolver beanNameViewResolver() { ... } ... } @Configuration public static class EnableWebMvcConfiguration extends DelegatingWebMvcConfiguration { @Bean @Override public RequestMappingHandlerAdapter requestMappingHandlerAdapter() { ... } @Bean @Primary @Override public RequestMappingHandlerMapping requestMappingHandlerMapping() { ... } } ... }
註解部分:
裝配順序:
代碼部分:
這部分就比較直接了,實例化了和 Web MVC 相關的Bean,如 HandlerAdapter、HandlerMapping、ViewResolver等。其中,出現了 DelegatingWebMvcConfiguration 類,這是 @EnableWebMvc 所 @Import導入的配置類。
能夠看到,在Spring Boot 自動裝配的類中,通過了一系列的 @Conditional 條件判斷,而後實例化某個模塊須要的Bean,且無需咱們配置任何東西。
在構造 SpringApplication 啓動類時,初始化了幾個重要的類,如 WebApplicationType 、ApplicationContextInitializer、ApplicationListener。其中 WebApplicationType 存儲的是當前應用類型,如 Servlet Web 、Reactive Web; ApplicationContextInitializer 和 ApplicationListener 則是 SpringBoot 經過擴展 Spring 特性建立的初始化器及監聽器。
SpringApplication 準備階段結束後,按道理應該進入運行階段,但運行階段以前還有一個操做,就是能夠修改 SpringApplication 默認配置。開頭的代碼示例能夠看到,應用程序主類中的main方法中寫的都是SpringApplication.run(xx.class),可能這種寫法不知足咱們的需求,咱們能夠對SpringApplication進行一些配置,例如關閉Banner,設置一些默認的屬性等。下面則是利用 SpringApplicationBuilder 的方式來添加配置:
@SpringBootApplication public class DiveInSpringBootApplication { public static void main(String[] args) { new SpringApplicationBuilder(DiveInSpringBootApplication.class) // 設置當前應用類型 .web(WebApplicationType.SERVLET) // 設置 banner 橫幅打印方式、有關閉、日誌、控制檯 .bannerMode(Banner.Mode.OFF) // 設置自定義的 banner .banner() // 追加自定義的 initializer 到集合中 .initializers() // 追加自定義的 listeners 到集合中 .listeners() .run(args); } }
使用該方式實現的SpringApplication能夠對其添加自定義的配置。
四、SpringApplication啓動類運行階段在 SpringApplication 運行階段中,先是經過擴展 Spring 監聽機制,在 SpringBoot 各個階段發佈不一樣事件,執行多個事件監聽器;而後建立 Environment 類,這是外部化配置的核心類;最後啓動 Spring 容器,經過 WebApplicationType 斷定當前應用類型,建立應用對應 ApplicationContext 應用上下文,再調用 ApplicationContext#refresh 方法啓動容器。
五、外部化配置之Environment外部化配置的幾種資源類型,如 properties、YAML、環境變量、系統屬性、啓動參數等。還詳細介紹了 Environment 類,該類是外部化配置核心類,全部外部化配置數據,都保存在該類中,並和你們討論了整個存儲流程。
六、外部化配置之@ConfigurationProperties@ConfigurationProperties 是 SpringBoot 實現外部化配置的重要註解,配合 SprinBoot 自動裝配特性來達到快速開發的目的。主要將 properties 配置文件和 Properties 配置類中的屬性進行映射,一樣也和你們討論了整個映射流程。
當 Spring Boot 集成外部組件後,就可在 properties 或 YAML 配置文件中定義組件須要的屬性,如 Redis 組件:
spring.redis.url=redis://user:password@example.com:6379 spring.redis.host=localhost spring.redis.password=123456 spring.redis.port=6379
其中都是以 spring.redis 爲前綴。這實際上是 Spring Boot 爲每一個組件提供了對應的 Properties 配置類,並將配置文件中的屬性值給映射到配置類中,並且它們有個特色,都是以 Properties 結尾,如 Redis 對應的配置類是 RedisProperties:
@ConfigurationProperties(prefix = "spring.redis") public class RedisProperties { private String url; private String host = "localhost"; private String password; private int port = 6379; ... }
@ConfigurationProperties 的註解,它的 prefix 參數就是約定好的前綴。該註解的功能就是將配置文件中的屬性和 Properties 配置類中的屬性進行映射,來達到自動配置的目的。這個過程分爲兩步,第一步是註冊 Properties 配置類,第二步是綁定配置屬性,過程當中還涉及到一個註解,它就是 @EnableConfigurationProperties ,該註解是用來觸發那兩步操做的。
Spring Boot 外部化配置作一個總體的總結:
傳統 Spring 應用需手動建立和啓動 Web 容器,在 SpringBoot 中,則是嵌入式的方式自動建立和啓動。SpringBoot 支持的 Web 容器類型有 Servlet Web 容器和 Reactive Web 容器,它們都有具體容器實現,Sevlet Web 對應的是 Tomcat、Jetty、Undertow,默認實現是 Tomcat;Reactive Web 對應的是 Netty 。
八、Starter機制之自定義Starter在 Spring 時代,搭建一個 Web 應用一般須要在 pom 文件中引入多個 Web 模塊相關的 Maven 依賴,如 SpringMvc、Tomcat 等依賴,而 SpringBoot 則只需引入 spring-boot-starter-web 依賴便可。這就是 SpringBoot 的 Starter 特性,用來簡化項目初始搭建以及開發過程,它是一個功能模塊的全部 Maven 依賴集合體。
SpringBoot 提供了很是多的 Starter,下面列出經常使用的幾個:
名稱 | 功能 |
---|---|
spring-boot-starter-web | 支持 Web 開發,包括 Tomcat 和 spring-webmvc |
spring-boot-starter-redis | 支持 Redis 鍵值存儲數據庫,包括 spring-redis |
spring-boot-starter-test | 支持常規的測試依賴,包括 JUnit、Hamcrest、Mockito 以及 spring-test 模塊 |
spring-boot-starter-aop | 支持面向切面的編程即 AOP,包括 spring-aop 和 AspectJ |
spring-boot-starter-jdbc | 支持JDBC數據庫 |
spring-boot-starter-data-jpa | 支持 JPA ,包括 spring-data-jpa、spring-orm、Hibernate |