Spring Boot自動配置類


 
前提
1、一般來說,xxxAware接口,都提供了一個setXxx的方法,以便於其實現類將Xxx注入自身的xxx字段中,從而進行操作。
例如 ApplicationContextAware ,就提供了  void setApplicationContext(ApplicationContext applicationContext) throws BeansException,從而讓其實現可以直接操作 applicationContext 。
2、Spring中的 BeanFactory,這是訪問bean container 的root interface。其實現類的對象通常擁有一系列 bean 定義,並以不同的String 名字來區分。
但是,官方文檔不建議直接使用這種方式獲取bean,而是建議使用注入的方式獲取bean( @Autowire)。--這個,前期不能使用初始化注入吧?
 

正文

Spring Boot提供的自動配置都是位於包 org.springframework.boot.autoconfigure 之下。

注意,
       ① 這里是Spring Boot提供的,而非第三方(如MyBatis-Spring-Boot-Starter)提供的。
       ② 不包含Spring Boot Actuator部分的。 
 
Spring Boot的自動配置類可以通過autoconfig report查看,需要開啟 --debug-Debug。或者在 Actuator 項目的autoconfig 端點查看。
 
這里先從Web開始學習
由於Spring Boot的web Starter集成了Spring MVC,而非其他,所以實際上提供的Web自動配置為Spring MVC的自動配置。
Spring MVC的自動配置在包 org.springframework.boot.autoconfigure.web 之下,該包中的內容如下:

 


從上圖中可以清楚的看到Spring Boot為Spring MVC提供了哪些自動配置:
  • DispatcherServletAutoConfiguration.class
  • EmbeddedServletContainerAutoConfiguration.class
  • ErrorMvcAutoConfiguration.class
  • GsonHttpMessageConvertersConfiguration.class
  • HttpEncodingAutoConfiguration.class
  • HttpMessageConvertersAutoConfiguration.class
  • JacksonHttpMessageConvertersConfiguration.class
  • MultipartAutoConfiguration.class
  • ServerPropertiesAutoConfiguration.class
  • WebClientAutoConfiguration.class
  • WebMvcAutoConfiguration.class
另外,還有一類文件: xxxProperties.class。這些文件都是  @ConfigurationProperties classes 。
在  @Configuration classes上可以使用  @EnableConfigurationProperties 進行  @ConfigurationProperties classes 的注入。 -- 也可以在 @Configuration classes內部使用 @Bean,略麻煩。
 
接下來,我們有針對性的來捋一遍。
 
先看一下這些類的聲明
 1 @AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE)
 2 @Configuration
 3 @ConditionalOnWebApplication
 4 @ConditionalOnClass(DispatcherServlet.class)
 5 @AutoConfigureAfter(EmbeddedServletContainerAutoConfiguration.class)
 6 public class DispatcherServletAutoConfiguration { ... }
 7 
 8 @AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE)
 9 @Configuration
10 @ConditionalOnWebApplication
11 @Import(BeanPostProcessorsRegistrar.class)
12 public class EmbeddedServletContainerAutoConfiguration { ... }
13 
14 @Configuration
15 @ConditionalOnClass(Gson.class)
16 class GsonHttpMessageConvertersConfiguration { ... }
17 
18 @Configuration
19 @EnableConfigurationProperties(HttpEncodingProperties.class)
20 @ConditionalOnWebApplication
21 @ConditionalOnClass(CharacterEncodingFilter.class)
22 @ConditionalOnProperty(prefix = "spring.http.encoding", value = "enabled", matchIfMissing = true)
23 public class HttpEncodingAutoConfiguration { ... }
24 
25 @Configuration
26 @ConditionalOnClass(HttpMessageConverter.class)
27 @AutoConfigureAfter({ GsonAutoConfiguration.class, JacksonAutoConfiguration.class })
28 @Import({ JacksonHttpMessageConvertersConfiguration.class, GsonHttpMessageConvertersConfiguration.class })
29 public class HttpMessageConvertersAutoConfiguration { ... }
30 
31 @Configuration
32 class JacksonHttpMessageConvertersConfiguration{ ... }
33 
34 @Configuration
35 @ConditionalOnClass({ Servlet.class, StandardServletMultipartResolver.class, MultipartConfigElement.class })
36 @ConditionalOnProperty(prefix = "spring.http.multipart", name = "enabled", matchIfMissing = true)
37 @EnableConfigurationProperties(MultipartProperties.class)
38 public class MultipartAutoConfiguration { ... }
39 
40 @Configuration
41 @EnableConfigurationProperties
42 @ConditionalOnWebApplication
43 public class ServerPropertiesAutoConfiguration { ... }
44 
45 @Configuration
46 @AutoConfigureAfter(HttpMessageConvertersAutoConfiguration.class)
47 public class WebClientAutoConfiguration { ... }
48 
49 @Configuration
50 @ConditionalOnWebApplication
51 @ConditionalOnClass({ Servlet.class, DispatcherServlet.class, WebMvcConfigurerAdapter.class })
52 @ConditionalOnMissingBean(WebMvcConfigurationSupport.class)
53 @AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE + 10)
54 @AutoConfigureAfter(DispatcherServletAutoConfiguration.class)
55 public class WebMvcAutoConfiguration { ... }
View Code
整理一下 優先級
最高級
         EmbeddedServletContainerAutoConfiguration
         DispatcherServletAutoConfiguration 
次高級
         WebMvcAutoConfiguration
無級別
         HttpEncodingAutoConfiguration
         MultipartAutoConfiguration
         ServerPropertiesAutoConfiguration
  依賴鏈(屬於無級別)
         GsonHttpMessageConvertersConfiguration
        JacksonHttpMessageConvertersConfiguration
        HttpMessageConvertersAutoConfiguration
         WebClientAutoConfiguration
 
一、先看一下 EmbeddedServletContainerAutoConfiguration,這是內置Servlet容器的自動配置 -- 默認就是那個 pivotal-tc-server (定制版tomcat,商業的)。
該類的聲明如下:
 1 @AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE) // 自動配置里面的最高優先級
 2 @Configuration
 3 @ConditionalOnWebApplication // 僅限於web應用
 4 @Import(BeanPostProcessorsRegistrar.class) // 導入內置容器的設置
 5 public class EmbeddedServletContainerAutoConfiguration {
 6     @Configuration
 7     @ConditionalOnClass({ Servlet.class, Tomcat.class })
 8     @ConditionalOnMissingBean(value = EmbeddedServletContainerFactory.class, search = SearchStrategy.CURRENT)
 9     public static class EmbeddedTomcat {
10         // ...
11     }
12 
13     @Configuration
14     @ConditionalOnClass({ Servlet.class, Server.class, Loader.class, WebAppContext.class })
15     @ConditionalOnMissingBean(value = EmbeddedServletContainerFactory.class, search = SearchStrategy.CURRENT)
16     public static class EmbeddedJetty {
17         // ...
18     }
19 
20     @Configuration
21     @ConditionalOnClass({ Servlet.class, Undertow.class, SslClientAuthMode.class })
22     @ConditionalOnMissingBean(value = EmbeddedServletContainerFactory.class, search = SearchStrategy.CURRENT)
23     public static class EmbeddedUndertow {
24         // ...
25     }
26 
27     public static class BeanPostProcessorsRegistrar implements ImportBeanDefinitionRegistrar, BeanFactoryAware {
28         // ...
29     }
30 }
 
@ConditionalOnWebApplication 是基於application context 是否 web application context 進行判斷。
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE) ,這里的 Ordered.HIGHEST_PRECEDENCE  其實是int類型的最小值,代表最高的優先級。
@Import(BeanPostProcessorsRegistrar.class,這里 BeanPostProcessorsRegistrar 中進行的操作是注冊了一個bean,  EmbeddedServletContainerCustomizerBeanPostProcessor 。是通過 ImportBeanDefinitionRegistrar  進行早期注冊。
 
這個配置類,內部共有4個靜態內部類:3個容器類(tomcat、jetty、undertow)、1個bean注冊類。
  1. 3個容器類是基於classpath中的class文件來判斷使用哪個容器,默認使用內置容器。
  2. 1個bean注冊類則是注冊了一個 BeanPostProcessor bean,用於對容器進行定制。
 
下面重點看一下這個bean注冊類的相關。
1、 EmbeddedServletContainerCustomizerBeanPostProcessor
public class EmbeddedServletContainerCustomizerBeanPostProcessor implements BeanPostProcessor, ApplicationContextAware {
    // ...
}

2、BeanPostProcessor接口,該接口內容如下:

1 public interface BeanPostProcessor {
2     Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;
3     Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;
4 }
View Code

根據方法的名字可以知道這是對在bean初始化之前、之后進行操作的方法。

該接口的Javadoc如下:
  1. BeanPostProcessor則是一個工廠鈎子(factory hook),用於對新beans實例進行定制修改,例如檢查它們的標記接口或者使用代理包裝它們。
  2. ApplicationContexts能夠自動探測BeanPostProcessor beans,並將他們應用到后續創建的任意beans中。
  3. 簡單bean工廠允許代碼化的注冊post-processors,並將注冊的post-processors應用到該工廠創建的所有bean中。
  4. 典型的做法是,通過標記接口裝配beans時,post-processors會實現postProcessBeforeInitialization;而使用代理包裝beans時則會實現postProcessAfterInitialization
EmbeddedServletContainerCustomizerBeanPostProcessor 中提供了 postProcessBeforeInitialization 的實現(對bean有更多的操作,而非直接返回bean),對內置容器進行了定制操作。(插一句,這里的定制操作是通過applicationContext 中 EmbeddedServletContainerCustomizer beans進行的,所以需要先獲取applicationContext(ApplicationContextAware的功勞),再從applicationContext中獲取EmbeddedServletContainerCustomizer beans)
3、回過頭來再看一下 BeanPostProcessorsRegistrar
1 public static class BeanPostProcessorsRegistrar implements ImportBeanDefinitionRegistrar, BeanFactoryAware {
2     // ...
3 }
View Code

這是個靜態內部類,實現了兩個接口。

 
4、接口 ImportBeanDefinitionRegistrar
public interface ImportBeanDefinitionRegistrar {
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry);
}

該接口用於在系統處理@Configuration class時注冊更多的bean。是bean定義級別的操作,而非@Bean method/instance級別的。

這個方法,應該是在Spring加載bean時被Spring調用。
org.springframework.context.annotation. ConfigurationClassBeanDefinitionReader

 

未完待續。

 

 
 
 
 
 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM