Spring Boot默認Initializer(1)——ConfigurationWarningsApplicationContextInitializer


ConfigurationWarningsApplicationContextInitializer的作用是用來報告Spring容器的一些常見的錯誤配置的。這個類中定義了兩個內部類:

       1. 定義了一個Check接口及它的實現類ComponentScanPackageCheck(以靜態內部類形式定義)

       2. 定義了一個BeanDefinitionRegistryPostProcessor接口的實現類(以靜態內部類形式定義)

因此我把這兩個內部類理解成ConfigurationWarningsApplicationContextInitializer的組合成員,類圖附在最后,

 initialize()方法,獲取Check的實例,然后構建出一個ConfigurationWarningsPostProcessor實例,注冊到Sring的容器中
public void initialize(ConfigurableApplicationContext context) {
        context.addBeanFactoryPostProcessor(
                new ConfigurationWarningsPostProcessor(getChecks()));
    }

 ConfigurationWarningsPostProcessor是BeanDefinitionRegistryPostProcessor接口的實現類,而BeanDefinitionRegistryPostProcessor接口又繼承於BeanFactoryPostProcessor接口,下面依次了解下這幾個Spring的接口和類圖:

 BeanFactoryPostProcessor接口:允許對spring容器的bean definition進行自定義的修改,可改變容器底層管理的bean的屬性值。Spring容器會自動檢測容器的bean definition中有沒實現了BeanFactoryPostProcessor接口的Bean ,如果有話將會在創建其他Bean之前首先執行該接口的代碼。

 BeanDefinitionRegistryPostProcessor接口:對BeanFactoryPostProcessor接口的一個擴展,允許在Spring容器會自動檢測容器的bean definition之前,進一步的注冊bean definiton到容器中。特定情況下還可以通過進一步的注冊bean definiton而反過來定義BeanFactoryPostProcessor接口的實例

 BeanDefinitionRegistry接口:作用主要是向注冊表中注冊 BeanDefinition 實例

 

搞清楚相關接口的用意后,我們看一下 ConfigurationWarningsPostProcessor 實現BeanDefinitionRegistryPostProcessor接口BeanFactoryPostProcessor接口做了哪些事情,主要是看兩個方法:


//這是實現BeanFactoryPostProcessor接口的方法,沒做任何事
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { } //這個是實現BeanDefinitionRegistryPostProcessor接口的方法,主要是把在注冊BeanDefinition實例過程中產生的告警信息傳給Check接口的實例進行處理產生要告警的內容,沒進行告警輸出 public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException { for (Check check : this.checks) { String message = check.getWarning(registry); if (StringUtils.hasLength(message)) { warn(message); //通過日志打印出告警信息 } } }

由此可見 ConfigurationWarningsPostProcessor 的主要作用就是把在注冊BeanDefinition實例過程中產生的告警信息傳給Check接口的實例進行處理,ConfigurationWarningsApplicationContextInitializer中只提供了一個Check的實現 ComponentScanPackageCheck,簡單分析下 ComponentScanPackageCheck類的源碼:

        //這個方法是實現了Check接口的接口方法
        public String getWarning(BeanDefinitionRegistry registry) {
            Set<String> scannedPackages = getComponentScanningPackages(registry);
            List<String> problematicPackages = getProblematicPackages(scannedPackages); //獲取有在掃描包范圍內的有警告的包 if (problematicPackages.isEmpty()) {
                return null;
            }
            return "Your ApplicationContext is unlikely to "
                    + "start due to a @ComponentScan of "
                    + StringUtils.collectionToDelimitedString(problematicPackages, ", ")
                    + ".";
        }
        
//獲取Spring容器要掃描的包
protected Set<String> getComponentScanningPackages( BeanDefinitionRegistry registry) { Set<String> packages = new LinkedHashSet<String>(); String[] names = registry.getBeanDefinitionNames(); for (String name : names) { BeanDefinition definition = registry.getBeanDefinition(name); if (definition instanceof AnnotatedBeanDefinition) { AnnotatedBeanDefinition annotatedDefinition = (AnnotatedBeanDefinition) definition; addComponentScanningPackages(packages, annotatedDefinition.getMetadata()); //從每個definition中獲取要掃描的包,並加入到packages集合中 } } return packages; }

以下是打印告警信息的方法,這個方法 還是位於 ConfigurationWarningsPostProcessor 類中,這個方法會由Spring容器在檢測處理BeanFactoryPostProcessor接口的bean definition時觸發並執行:

public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry)
                throws BeansException {
            for (Check check : this.checks) {
                String message = check.getWarning(registry);
                if (StringUtils.hasLength(message)) {
                    warn(message);
                }
            }

        }

 

 


免責聲明!

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



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