走心Springboot源碼解析: 4、refresh方法

打個廣告

我的想寫《springboot源碼解析》這一系列好久了,可是一直角兒心底的知識積累不足,因此一直沒有動筆。 因此想找一些小夥伴一塊兒寫這一系列,互相糾錯交流學習。 若是有小夥伴有興趣一塊兒把這一系列的講解寫完的話,加下我微信:13670426148,咱們一塊兒完成,當交流學習。 後期還想寫一系列介紹rpc框架的,不過要再過一陣子了,先把springboot的寫完java

前言

直接講了 refresh() 的代碼實現,直到完成配置類的實例化爲止,後面的registerBeanPostProcessors方法還沒開始講。spring

refresh總方法

public void refresh() throws BeansException, IllegalStateException {
        //由於該過程必須是同步的,因此進行加鎖處理
        synchronized(this.startupShutdownMonitor) {
            // 1. 容器刷新前的準備,設置上下文,獲取屬性,驗證必要的屬性
            this.prepareRefresh();
            // 2. 銷燬原先的 beanFactory,建立新的bean工廠,
            ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();
            // 3. 配置標準的beanFactory,設置ClassLoader,設置SpEL表達式解析器等等
            this.prepareBeanFactory(beanFactory);

            try {
                // 4. 添加一個BeanPostProcessor到bean工廠中,類型爲WebApplicationContextServletContextAwareProcessor(this)
                // 任意Bean均可以很方便的獲取到ServletContext。
                this.postProcessBeanFactory(beanFactory);
                this.invokeBeanFactoryPostProcessors(beanFactory);
                this.registerBeanPostProcessors(beanFactory);
                this.initMessageSource();
                this.initApplicationEventMulticaster();
                this.onRefresh();
                this.registerListeners();
                this.finishBeanFactoryInitialization(beanFactory);
                this.finishRefresh();
            } catch (BeansException var9) {
                if (this.logger.isWarnEnabled()) {
                    this.logger.warn("Exception encountered during context initialization - cancelling refresh attempt: " + var9);
                }

                this.destroyBeans();
                this.cancelRefresh(var9);
                throw var9;
            } finally {
                this.resetCommonCaches();
            }

        }
    }

複製代碼

1. prepareRefresh()刷新容器前的準備

protected void prepareRefresh() {
        this.startupDate = System.currentTimeMillis();
        this.closed.set(false);
        this.active.set(true);
        if (this.logger.isDebugEnabled()) {
            if (this.logger.isTraceEnabled()) {
                this.logger.trace("Refreshing " + this);
            } else {
                this.logger.debug("Refreshing " + this.getDisplayName());
            }
        }
		// 初始化 propertySources
        this.initPropertySources();
     	//getEnvironment 得到的是 StandardEnvironment
     	//檢驗屬性的合法等 
        this.getEnvironment().validateRequiredProperties();
        if (this.earlyApplicationListeners == null) {
            this.earlyApplicationListeners = new 
                // 此時的監聽器有12個了,以下圖1.1所示
                LinkedHashSet(this.applicationListeners);
        } else {
            this.applicationListeners.clear();
            this.applicationListeners.addAll(this.earlyApplicationListeners);
        }
		// 默認是一個空的set
        this.earlyApplicationEvents = new LinkedHashSet();
    }

複製代碼

圖1.1 : 編程

2. 建立新的beanFactory

兩步,第一步建立新的beanFactory,第二步是進行基本的配置數組

1.建立新的beanFacotry,實際建立的爲DefaultListableBeanFactory

protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
        //在application中建立DefaultListableBeanFactory並賦值給上下文中的this.beanFactory,至關於原先那個不要了,建立一個新的.
        this.refreshBeanFactory();
        return this.getBeanFactory();
}
複製代碼

其中refreshBeanFactory()方法是經過 GenericApplicationContext來執行的這個springboot

public class GenericApplicationContext extends AbstractApplicationContext implements BeanDefinitionRegistry {
    // 構造器裏面就建立了DefaultListableBeanFactory了
    public GenericApplicationContext() {
        this.customClassLoader = false;
        this.refreshed = new AtomicBoolean();
        this.beanFactory = new DefaultListableBeanFactory();
    }
    
    // 
    protected final void refreshBeanFactory() throws IllegalStateException {
        if (!this.refreshed.compareAndSet(false, true)) {
            throw new IllegalStateException("GenericApplicationContext does not support multiple refresh attempts: just call 'refresh' once");
        } else {
            this.beanFactory.setSerializationId(this.getId());
        }
    }
    
}

複製代碼

2. 配置beanFactory

protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
    	// 設置beanFactory的classLoader爲當前context的classLoader
        beanFactory.setBeanClassLoader(this.getClassLoader());
   		 // 設置EL表達式解析器(Bean初始化完成後填充屬性時會用到)
		// spring3增長了表達式語言的支持,默承認以使用#{bean.xxx}的形式來調用相關屬性值
        beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
    	// 設置屬性註冊解析器PropertyEditor 這個主要是對bean的屬性等設置管理的一個工具
        beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, this.getEnvironment()));
    	// 將當前的ApplicationContext對象交給ApplicationContextAwareProcessor類來處理,從而在Aware接口實現類中的注入applicationContext等等
		// 添加了一個處理aware相關接口的beanPostProcessor擴展,主要是使用beanPostProcessor的postProcessBeforeInitialization()前置處理方法實現aware相關接口的功能
		// 相似的還有ResourceLoaderAware、ServletContextAware等等等等
        beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
    	// 下面是忽略的自動裝配(也就是實現了這些接口的Bean,不要Autowired自動裝配了)
		// 默認只有BeanFactoryAware被忽略,因此其它的須要自行設置
		// 由於ApplicationContextAwareProcessor把這5個接口的實現工做作了
        beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
        beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
        beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
        beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
        beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
        beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
        beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
        beanFactory.registerResolvableDependency(ResourceLoader.class, this);
        beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
        beanFactory.registerResolvableDependency(ApplicationContext.class, this);
        beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));
    	// 注入一些其它信息的bean,好比environment、systemProperties、SystemEnvironment等
        if (beanFactory.containsBean("loadTimeWeaver")) {
            beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
            beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
        }

        if (!beanFactory.containsLocalBean("environment")) {
            beanFactory.registerSingleton("environment", this.getEnvironment());
        }

        if (!beanFactory.containsLocalBean("systemProperties")) {
            beanFactory.registerSingleton("systemProperties", this.getEnvironment().getSystemProperties());
        }

        if (!beanFactory.containsLocalBean("systemEnvironment")) {
            beanFactory.registerSingleton("systemEnvironment", this.getEnvironment().getSystemEnvironment());
        }

    }
複製代碼

DefaultListableBeanFactory的父類 AbstractBeanFactory中有 List<BeanPostProcessor> beanPostProcessors 此時beanPostProcessors中的內容有 圖1.2: bash

DefaultListableBeanFactory 中存在的是 beanDefinitionMapresolvableDependenciesbeanDefinitionNamesmanualSingletonNames微信

beanDefinitionNames記錄了建立了的beanDefinition的類型集合,beanDefinitionMap存放的是beanDefinition映射。迄今爲止已經存在的有: 圖1.3 app

registerSingleton是在 DefaultSingletonBeanRegistry類中的框架

//先看DefaultListableBeanFactory的registerSingleton方法:
public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable {
    public void registerSingleton(String beanName, Object singletonObject) throws IllegalStateException {
        super.registerSingleton(beanName, singletonObject);
        if (this.hasBeanCreationStarted()) {
            synchronized(this.beanDefinitionMap) {
                if (!this.beanDefinitionMap.containsKey(beanName)) {
                    Set<String> updatedSingletons = new LinkedHashSet(this.manualSingletonNames.size() + 1);
                    updatedSingletons.addAll(this.manualSingletonNames);
                    updatedSingletons.add(beanName);
                    this.manualSingletonNames = updatedSingletons;
                }
            }
        } else if (!this.beanDefinitionMap.containsKey(beanName)) {
        // manualSingletonNames存放已經實例化好單例對象
            this.manualSingletonNames.add(beanName);
        }

        this.clearByTypeCache();
    }
}
複製代碼
public class DefaultSingletonBeanRegistry {
    public void registerSingleton(String beanName, Object singletonObject) throws IllegalStateException {
        Assert.notNull(beanName, "Bean name must not be null");
        Assert.notNull(singletonObject, "Singleton object must not be null");
        synchronized(this.singletonObjects) {
            Object oldObject = this.singletonObjects.get(beanName);
            if (oldObject != null) {
                throw new IllegalStateException("Could not register object [" + singletonObject + "] under bean name '" + beanName + "': there is already object [" + oldObject + "] bound");
            } else {
                this.addSingleton(beanName, singletonObject);
            }
        }
    }
    
    protected void addSingleton(String beanName, Object singletonObject) {
        //這個是直接實例化了
        synchronized(this.singletonObjects) {
            this.singletonObjects.put(beanName, singletonObject);
            this.singletonFactories.remove(beanName);
            this.earlySingletonObjects.remove(beanName);
            this.registeredSingletons.add(beanName);
        }
    }
}
複製代碼

他們之間的差異是,bean先讀取到 beanDefinition中,等到統一實例化的時候,再根據beanDefinition的信息,調用DefaultSingletonBeanRegistry類的registerSingleton方法註冊bean到 beanFactory中。在這裏面涉及到的類有 DefaultSingletonBeanRegistryDefaultListableBeanFactoryAbstractBeanFactory工具

  • DefaultSingletonBeanRegistry是在實例化bean的時候用到的,實例化好的單例類信息都存放在其中
  • DefaultListableBeanFactory 是在xml掃描或者註解掃描類時候組裝BeanDefinition的過程用到的類
  • AbstractBeanFactory是配置工廠基本配置信息,好比BeanPostProcessor類,或者註冊解析器PropertyEditor等時候用到

不得不說「單一職責原則」在這裏體現的挺充分的,每一個類都有各自的意義。

3. 註冊後置處理器BeanPostProcessor

添加一個BeanPostProcessor到bean工廠中,類型爲WebApplicationContextServletContextAwareProcessor(this) 任意Bean均可以很方便的獲取到ServletContext。 postProcessBeanFactory方法是父類AnnotationConfigServletWebServerApplicationContext中的

public class AnnotationConfigServletWebServerApplicationContext extends ServletWebServerApplicationContext implements AnnotationConfigRegistry {

     protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
     //調用父類ServletWebServerApplicationContext的postProcessBeanFactory方法
        super.postProcessBeanFactory(beanFactory);
        if (this.basePackages != null && this.basePackages.length > 0) {
            this.scanner.scan(this.basePackages);
        }

        if (!this.annotatedClasses.isEmpty()) {
            this.reader.register(ClassUtils.toClassArray(this.annotatedClasses));
        }

    }
}
    
    protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
        // 添加到AbstractBeanFactory的List<BeanPostProcessors>中
        // 註冊ServletContextAwareProcessor 這樣任意Bean均可以很方便的獲取到ServletContext了 同時忽略ServletContextAware,由於ServletContextAwareProcessor 都把事情都作了
        beanFactory.addBeanPostProcessor(new WebApplicationContextServletContextAwareProcessor(this));
        beanFactory.ignoreDependencyInterface(ServletContextAware.class);
        this.registerWebApplicationScopes();
    }


複製代碼

到了如今 AbstractBeanFactory 中的 BeanPostProcessors 有3個了.

4. 執行 Bean工廠後置處理器BeanFactoryPostProcessor

invokeBeanFactoryPostProcessors 方法是在AbstractApplicationContext.class中實現的

public abstract class AbstractApplicationContext extends DefaultResourceLoader implements ConfigurableApplicationContext {
     public void refresh() throws BeansException, IllegalStateException {
         ...
        //此時beanFactory是DefaultListableBeanFactory
        this.invokeBeanFactoryPostProcessors(beanFactory);
        ...
     }
    
    protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
        //this.getBeanFactoryPostProcessors(),得到到的是BeanFactoryPostProcessors跟上一步的BeanPostProcessors不同
        // 交給PostProcessorRegistration處理
        PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, this.getBeanFactoryPostProcessors());
        if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean("loadTimeWeaver")) {
            beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
            beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
        }
    }
 
}
複製代碼

BeanFactoryPostProcessors 跟上一步的 BeanPostProcessors 不同

  • BeanFactoryPostProcessors是存放在AbstractApplicationContext
  • BeanPostProcessors是存放在AbstractBeanFactory中的。

交給PostProcessorRegistrationDelegate處理

//Delegate是一個解析器,不少都會這麼操做,把一些任務交給一個解析器去完成
final class PostProcessorRegistrationDelegate {
    //此時獲取到的後置處理器有3個, 查看圖1.5
    public static void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {
        Set<String> processedBeans = new HashSet();
        // 此處安放了兩個容器,一個裝載普通的BeanFactoryPostProcessor
		// 另一個裝載和Bean定義有關的 BeanDefinitionRegistryPostProcessor
		// 差異就是BeanDefinitionRegistryPostProcessor裏面多了一個postProcessBeanDefinitionRegistry方法,能夠用來註冊bean的
        ArrayList regularPostProcessors;
        ArrayList registryProcessors;
        int var9;
        ArrayList currentRegistryProcessors;
        String[] postProcessorNames;
        // 確定是要BeanDefinitionRegistry的子類纔會執行下面的內容
        if (beanFactory instanceof BeanDefinitionRegistry) {
            BeanDefinitionRegistry registry = (BeanDefinitionRegistry)beanFactory;
            regularPostProcessors = new ArrayList();
            registryProcessors = new ArrayList();
            Iterator var6 = beanFactoryPostProcessors.iterator();
            
            while(var6.hasNext()) {
                BeanFactoryPostProcessor postProcessor = (BeanFactoryPostProcessor)var6.next();
                // 分別裝成registryProcessors 或者 普通的regularPostProcessors
                if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
                    BeanDefinitionRegistryPostProcessor registryProcessor = (BeanDefinitionRegistryPostProcessor)postProcessor;
                    //1. 若是是bean定義有關的BeanDefinitionRegistryPostProcessor的話還要先執行其postProcessBeanDefinitionRegistry
                    registryProcessor.postProcessBeanDefinitionRegistry(registry);
                    registryProcessors.add(registryProcessor);
                } else {
                    regularPostProcessors.add(postProcessor);
                }
            }
            
            currentRegistryProcessors = new ArrayList();
            //這裏獲得的是String : org.springframework.context.annotation.internalConfigurationAnnotationProcessor
            postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
            String[] var16 = postProcessorNames;
            var9 = postProcessorNames.length;

            int var10;
            String ppName;
            for(var10 = 0; var10 < var9; ++var10) {
                ppName = var16[var10];
                if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
                // currentRegistryProcessors裏面是 ConfigurationClassPostPorcessor,一個用來處理 Configuration註解或者Component註解等的後置處理器,很重要
                    currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
                    processedBeans.add(ppName);
                }
            }
            // 排序
            sortPostProcessors(currentRegistryProcessors, beanFactory);
            // 添加到registryProcessors中,此時registryProcessors中會有3個BeanDefinitionRegistryPostProcessor(通常狀況下,若是不本身定義的話)
            registryProcessors.addAll(currentRegistryProcessors);
            // 2. 此時執行ConfigurationClassPostPorcessor的解析操做,找到掃描包下全部的配置類
            // currentRegistryProcessors下面通常狀況下只有1個 ConfiguraionClassPostProcessor
            invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
            // 執行完以後, currentRegistryProcessors清空掉
            currentRegistryProcessors.clear();
            postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
            var16 = postProcessorNames;
            var9 = postProcessorNames.length;

            for(var10 = 0; var10 < var9; ++var10) {
                ppName = var16[var10];
                if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {
                    currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
                    processedBeans.add(ppName);
                }
            }
            
            sortPostProcessors(currentRegistryProcessors, beanFactory);
            registryProcessors.addAll(currentRegistryProcessors);
            invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
            currentRegistryProcessors.clear();
            boolean reiterate = true;

            while(reiterate) {
                reiterate = false;
                postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
                String[] var19 = postProcessorNames;
                var10 = postProcessorNames.length;

                for(int var26 = 0; var26 < var10; ++var26) {
                    String ppName = var19[var26];
                    if (!processedBeans.contains(ppName)) {
                        currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
                        processedBeans.add(ppName);
                        reiterate = true;
                    }
                }

                sortPostProcessors(currentRegistryProcessors, beanFactory);
                registryProcessors.addAll(currentRegistryProcessors);
                invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
                currentRegistryProcessors.clear();
            }

            invokeBeanFactoryPostProcessors((Collection)registryProcessors, (ConfigurableListableBeanFactory)beanFactory);
            invokeBeanFactoryPostProcessors((Collection)regularPostProcessors, (ConfigurableListableBeanFactory)beanFactory);
        } else {
            invokeBeanFactoryPostProcessors((Collection)beanFactoryPostProcessors, (ConfigurableListableBeanFactory)beanFactory);
        }

        String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);
        regularPostProcessors = new ArrayList();
        registryProcessors = new ArrayList();
        currentRegistryProcessors = new ArrayList();
        postProcessorNames = postProcessorNames;
        int var20 = postProcessorNames.length;

        String ppName;
        for(var9 = 0; var9 < var20; ++var9) {
            ppName = postProcessorNames[var9];
            if (!processedBeans.contains(ppName)) {
                if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
                    regularPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
                } else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
                    registryProcessors.add(ppName);
                } else {
                    currentRegistryProcessors.add(ppName);
                }
            }
        }

        sortPostProcessors(regularPostProcessors, beanFactory);
        invokeBeanFactoryPostProcessors((Collection)regularPostProcessors, (ConfigurableListableBeanFactory)beanFactory);
        List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList();
        Iterator var21 = registryProcessors.iterator();

        while(var21.hasNext()) {
            String postProcessorName = (String)var21.next();
            orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
        }

        sortPostProcessors(orderedPostProcessors, beanFactory);
        invokeBeanFactoryPostProcessors((Collection)orderedPostProcessors, (ConfigurableListableBeanFactory)beanFactory);
        List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList();
        Iterator var24 = currentRegistryProcessors.iterator();

        while(var24.hasNext()) {
            ppName = (String)var24.next();
            nonOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
        }

        invokeBeanFactoryPostProcessors((Collection)nonOrderedPostProcessors, (ConfigurableListableBeanFactory)beanFactory);
        beanFactory.clearMetadataCache();
    }
    
    
}

複製代碼

圖1.5:

1. bean定義有關的BeanDefinitionRegistryPostProcessor的執行

裏面總共有2個bean定義有關的後置處理器,第一個是 CachingMetadataReaderFactoryPostProcessor, 第二個是 ConfigurationWarningsApplicationContextInitializer

private static class CachingMetadataReaderFactoryPostProcessor implements BeanDefinitionRegistryPostProcessor, PriorityOrdered {
        private CachingMetadataReaderFactoryPostProcessor() {
        }

        public int getOrder() {
            return -2147483648;
        }

        public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        }

        public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
            // 在註冊表中註冊SharedMetadataReaderFactoryBean的BeanDefinition
            // registry.registerBeanDefinition("org.springframework.boot.autoconfigure.internalCachingMetadataReaderFactory", definition);
            // definition是包裝了SharedMetadataReaderFactoryContextInitializer.SharedMetadataReaderFactoryBean.class的bean, 再執行 beanDefinitionMap.put("org.springframework.boot.autoconfigure.internalCachingMetadataReaderFactory", definition)
            this.register(registry);
            this.configureConfigurationClassPostProcessor(registry);
        }

        private void register(BeanDefinitionRegistry registry) {
            // 用BeanDefinitionBuilder.genericBeanDefinition()方法,該方法是定義一個BeanDefinition, 這裏是SharedMetadataReaderFactoryBean
            BeanDefinition definition = BeanDefinitionBuilder.genericBeanDefinition(SharedMetadataReaderFactoryContextInitializer.SharedMetadataReaderFactoryBean.class, SharedMetadataReaderFactoryContextInitializer.SharedMetadataReaderFactoryBean::new).getBeanDefinition();
           
 // 在註冊表裏面註冊該bean信息,
 // internalCachingMetadataReaderFactory -> 這裏是 BeanDefinition
            		 registry.registerBeanDefinition("org.springframework.boot.autoconfigure.internalCachingMetadataReaderFactory", definition);
        }
		// 把一步註冊到註冊表中的 SharedMetadataReaderFactoryBean設置到 internalConfigurationAnnotationProcessor對應的BeanDefinition的 實例的metadataReaderFactory屬性中
        private void configureConfigurationClassPostProcessor(BeanDefinitionRegistry registry) {
            try {
                // 獲取internalConfigurationAnnotationProcessor這個bean,以後設置其屬性metadataReaderFactory的值爲類: org.springframework.boot.autoconfigure.internalCachingMetadataReaderFactory
                // 此時definition是ConfigurationClassPostProcessor
                BeanDefinition definition = registry.getBeanDefinition("org.springframework.context.annotation.internalConfigurationAnnotationProcessor");
                // 一個definition的propertyValues裏面就是定義了他實例時候的屬性的值,此時至關於給ConfigurationClassPostProcessor 的metadataReaderFactory屬性設置爲咱們上一步定義的internalCachingMetadataReaderFactory。
                definition.getPropertyValues().add("metadataReaderFactory", new RuntimeBeanReference("org.springframework.boot.autoconfigure.internalCachingMetadataReaderFactory"));
            } catch (NoSuchBeanDefinitionException var3) {
            }

        }
    }


// 第二個後置處理器是
// 作警告。
public class ConfigurationWarningsApplicationContextInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {
	// registry永遠都是DefaultListableBeanFactory
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
        //此時 this.checks是一個數組,裏面的元素只有1個
        //ConfigurationWarningsApplicationContextInitializer.ComponentScanPackageCheck
            ConfigurationWarningsApplicationContextInitializer.Check[] var2 = this.checks;
            int var3 = var2.length;

            for(int var4 = 0; var4 < var3; ++var4) {
                ConfigurationWarningsApplicationContextInitializer.Check check = var2[var4];
                String message = check.getWarning(registry);
                // 只是進行警告,若是沒有找到掃描路徑,則會作警告
                if (StringUtils.hasLength(message)) {
                    this.warn(message);
                }
            }

        }
}

 protected static class ComponentScanPackageCheck implements ConfigurationWarningsApplicationContextInitializer.Check {
        private static final Set<String> PROBLEM_PACKAGES;

        protected ComponentScanPackageCheck() {
        }

        public String getWarning(BeanDefinitionRegistry registry) {
            // 下面解釋
            Set<String> scannedPackages = this.getComponentScanningPackages(registry);
            List<String> problematicPackages = this.getProblematicPackages(scannedPackages);
            //能夠看到此時只是返回信息,而不是真的存儲起來.
            return problematicPackages.isEmpty() ? null : "Your ApplicationContext is unlikely to start due to a @ComponentScan of " + StringUtils.collectionToDelimitedString(problematicPackages, ", ") + ".";
        }
  
      
      
  }


public class ConfigurationWarningsApplicationContextInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {
    
    protected Set<String> getComponentScanningPackages(BeanDefinitionRegistry registry) {
            Set<String> packages = new LinkedHashSet();
        	// 得到至今爲止全部的註冊表中的Definitions中的Name集合,此時是7個,見圖5.2
            String[] names = registry.getBeanDefinitionNames();
            String[] var4 = names;
            int var5 = names.length;

            for(int var6 = 0; var6 < var5; ++var6) {
                String name = var4[var6];
                BeanDefinition definition = registry.getBeanDefinition(name);
                //判斷是什麼類型的 AnnotatedBeanDefinition,
                //這個比較重要了,由於以下圖除了啓動入口類(啓動入口類上通常定義了包掃描的路徑,而我項目中的啓動入口類是MallApplication.class)以外全部的都不是AnnotatedBeanDefinition的子類: AnnotatedGenericBeanDefinition
                if (definition instanceof AnnotatedBeanDefinition) {
                    AnnotatedBeanDefinition annotatedDefinition = (AnnotatedBeanDefinition)definition;
                // annotatedDefinition中Metadata的內容中就有其@ComponentScan註解的信息
                    this.addComponentScanningPackages(packages, annotatedDefinition.getMetadata());
                }
            }

            return packages;
        }
    
    
} 


protected Set<String> getComponentScanningPackages(BeanDefinitionRegistry registry) {
            Set<String> packages = new LinkedHashSet();
            String[] names = registry.getBeanDefinitionNames();
            String[] var4 = names;
            int var5 = names.length;

            for(int var6 = 0; var6 < var5; ++var6) {
                String name = var4[var6];
                BeanDefinition definition = registry.getBeanDefinition(name);
                if (definition instanceof AnnotatedBeanDefinition) {
                    AnnotatedBeanDefinition annotatedDefinition = (AnnotatedBeanDefinition)definition;
                    // 獲取其beanDefinition的信息
                    this.addComponentScanningPackages(packages, annotatedDefinition.getMetadata());
                }
            }
			// 像我項目這裏獲得的就是入口類的包路徑。
            return packages;
        }
// 獲取掃描的包路徑
private void addComponentScanningPackages(Set<String> packages, AnnotationMetadata metadata) {
    		//信息如圖5.3所示
            AnnotationAttributes attributes = AnnotationAttributes.fromMap(metadata.getAnnotationAttributes(ComponentScan.class.getName(), true));
            if (attributes != null) {
                this.addPackages(packages, attributes.getStringArray("value"));
                this.addPackages(packages, attributes.getStringArray("basePackages"));
                this.addClasses(packages, attributes.getStringArray("basePackageClasses"));
                //若是都找不到的話,直接找到該bean的包路徑
                if (packages.isEmpty()) {
                    packages.add(ClassUtils.getPackageName(metadata.getClassName()));
                }
            }

        }

複製代碼

2. 執行 ConfigurationClassPostPorcessor

//此時postProcessors是ConfigurationClassPostPorcessor
private static void invokeBeanDefinitionRegistryPostProcessors(Collection<? extends BeanDefinitionRegistryPostProcessor> postProcessors, BeanDefinitionRegistry registry) {
        Iterator var2 = postProcessors.iterator();

        while(var2.hasNext()) {
            BeanDefinitionRegistryPostProcessor postProcessor = (BeanDefinitionRegistryPostProcessor)var2.next();
            postProcessor.postProcessBeanDefinitionRegistry(registry);
        }

    }
複製代碼

仍是執行 ConfigurationClassPostProcessorprocessConfigBeanDefinitions() 方法

圖1.7:

//重點 : 開始解析配置類信息
解釋一下,先找到DefaultListableBeanFactory 裏面已經有了的BeanDefinition,判斷他們是否爲配置類,找到其中全部的配置類,找到其是否有@ComponentScan中掃描的包路徑。
public class ConfigurationClassPostProcessor {
     public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
        List<BeanDefinitionHolder> configCandidates = new ArrayList();
        // 獲取全部已經註冊的beanDefinition的名稱, 這裏是7個,如上圖1.7所示
        String[] candidateNames = registry.getBeanDefinitionNames();
        String[] var4 = candidateNames;
        int var5 = candidateNames.length;

        for(int var6 = 0; var6 < var5; ++var6) {
            String beanName = var4[var6];
            BeanDefinition beanDef = registry.getBeanDefinition(beanName);
            // 1.1 若是BeanDefinition 中的configurationClass 屬性爲full 或者lite ,則意味着已經處理過了,直接跳過
            if (!ConfigurationClassUtils.isFullConfigurationClass(beanDef) && !ConfigurationClassUtils.isLiteConfigurationClass(beanDef)) {
                // 1.2 判斷對應bean是否爲配置類,若是是,則加入到configCandidates.
                // 怎麼判斷是不是配置類呢,下面解析
                if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) {
                    //-----此時只有入口類 MallApplication 添加進來了, 把是配置類的BeanDefinitionHolder存進來到configCandidates中
                    configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));
                }
            } else if (this.logger.isDebugEnabled()) {
                this.logger.debug("Bean definition has already been processed as a configuration class: " + beanDef);
            }
        }
        
        if (!configCandidates.isEmpty()) {
            //對配置類BeanDefinitionHolder排序
            configCandidates.sort((bd1, bd2) -> {
                int i1 = ConfigurationClassUtils.getOrder(bd1.getBeanDefinition());
                int i2 = ConfigurationClassUtils.getOrder(bd2.getBeanDefinition());
                return Integer.compare(i1, i2);
            });
            SingletonBeanRegistry sbr = null;
            // registry仍是 DefualtListableBeanFactory
            if (registry instanceof SingletonBeanRegistry) {
                sbr = (SingletonBeanRegistry)registry;
                if (!this.localBeanNameGeneratorSet) {
                    // 名字生成器
                    BeanNameGenerator generator = (BeanNameGenerator)sbr.getSingleton("org.springframework.context.annotation.internalConfigurationBeanNameGenerator");
                    if (generator != null) {
                        // 名字生成器
                        this.componentScanBeanNameGenerator = generator;
                        this.importBeanNameGenerator = generator;
                    }
                }
            }
            // environment已是StandardServletEnvironment 了
            if (this.environment == null) {
                this.environment = new StandardEnvironment();
            }
            // 交給ConfigurationClassParser去處理,拿到配置類下的 @ComponentScan註解指定的掃描包路徑
            ConfigurationClassParser parser = new ConfigurationClassParser(this.metadataReaderFactory, this.problemReporter, this.environment, this.resourceLoader, this.componentScanBeanNameGenerator, registry);
            Set<BeanDefinitionHolder> candidates = new LinkedHashSet(configCandidates);
            HashSet alreadyParsed = new HashSet(configCandidates.size());
            // 有個循環的過程
            do {
                 //通常狀況下candidates初始是啓動入口類,在我本地項目調試是MallApplication.class,上面有@SpringApplication註解,該註解裏面默認存在了 @ComponentScan註解
                // parser的類型是 ConfigurationClassParser
                // 最終要的內容全在這裏面
                // 1.3. parse開始解析,把解析方法交給了 ConfigurationClassParser 去解析(下面講解)
                parser.parse(candidates);
                parser.validate();
                
                Set<ConfigurationClass> configClasses = new LinkedHashSet(parser.getConfigurationClasses());
                configClasses.removeAll(alreadyParsed);
                if (this.reader == null) {
                    this.reader = new ConfigurationClassBeanDefinitionReader(registry, this.sourceExtractor, this.resourceLoader, this.environment, this.importBeanNameGenerator, parser.getImportRegistry());
                }
                // 註冊解析到的bean
                this.reader.loadBeanDefinitions(configClasses);
                alreadyParsed.addAll(configClasses);
                candidates.clear();
                // candidateNames.length是未解析以前Bean的數量
                // registry.getBeanDefinitionCount()是如今Bean的數量
                // 主要是以Bean數量判斷是否有新的Bean註冊到IOC容器中去了
                  // 也就是說,這裏開始操做那些,新註冊進來的Bean
                if (registry.getBeanDefinitionCount() > candidateNames.length) {
                    String[] newCandidateNames = registry.getBeanDefinitionNames();
                    Set<String> oldCandidateNames = new HashSet(Arrays.asList(candidateNames));
                    Set<String> alreadyParsedClasses = new HashSet();
                    Iterator var12 = alreadyParsed.iterator();

                    while(var12.hasNext()) {
                        ConfigurationClass configurationClass = (ConfigurationClass)var12.next();
                        alreadyParsedClasses.add(configurationClass.getMetadata().getClassName());
                    }

                    String[] var23 = newCandidateNames;
                    int var24 = newCandidateNames.length;
                    
                    for(int var14 = 0; var14 < var24; ++var14) {
                        String candidateName = var23[var14];
                        if (!oldCandidateNames.contains(candidateName)) {
                            BeanDefinition bd = registry.getBeanDefinition(candidateName);
                            if (ConfigurationClassUtils.checkConfigurationClassCandidate(bd, this.metadataReaderFactory) && !alreadyParsedClasses.contains(bd.getBeanClassName())) {
                                candidates.add(new BeanDefinitionHolder(bd, candidateName));
                            }
                        }
                    }

                    candidateNames = newCandidateNames;
                }
            } while(!candidates.isEmpty());

            if (sbr != null && !sbr.containsSingleton(IMPORT_REGISTRY_BEAN_NAME)) {
                sbr.registerSingleton(IMPORT_REGISTRY_BEAN_NAME, parser.getImportRegistry());
            }

            if (this.metadataReaderFactory instanceof CachingMetadataReaderFactory) {
                ((CachingMetadataReaderFactory)this.metadataReaderFactory).clearCache();
            }

        }
    }
}

複製代碼

1.2 判斷其是不是配置類

ConfigurationClassUtils.checkConfigurationClassCandidate

//1.2 檢查對應bean是否爲配置類

abstract class ConfigurationClassUtils {
    
     public static boolean checkConfigurationClassCandidate(BeanDefinition beanDef, MetadataReaderFactory metadataReaderFactory) {
        //1. 獲取類名
        String className = beanDef.getBeanClassName();
        if (className != null && beanDef.getFactoryMethodName() == null) {
            Object metadata;
        //2. 若是BeanDefinition 是 AnnotatedBeanDefinition的實例,而且className 和 BeanDefinition中 的元數據 的類名相同
        // 則直接從BeanDefinition 得到Metadata
            if (beanDef instanceof AnnotatedBeanDefinition && className.equals(((AnnotatedBeanDefinition)beanDef).getMetadata().getClassName())) {
                metadata = ((AnnotatedBeanDefinition)beanDef).getMetadata();
            } else if (beanDef instanceof AbstractBeanDefinition && ((AbstractBeanDefinition)beanDef).hasBeanClass()) {
                // 若是BeanDefinition 是 AnnotatedBeanDefinition的實例,而且beanDef 有 beanClass 屬性存在
        // 則實例化StandardAnnotationMetadata
                Class<?> beanClass = ((AbstractBeanDefinition)beanDef).getBeanClass();
                metadata = new StandardAnnotationMetadata(beanClass, true);
            } else {
                try {
                    /// 2.3 不然 經過MetadataReaderFactory 中的MetadataReader 進行讀取
                    MetadataReader metadataReader = metadataReaderFactory.getMetadataReader(className);
                    metadata = metadataReader.getAnnotationMetadata();
                } catch (IOException var5) {
                    if (logger.isDebugEnabled()) {
                        logger.debug("Could not find class file for introspecting configuration annotations: " + className, var5);
                    }

                    return false;
                }
            }
		//3. 前兩步的內容不重要,重要的是下面
		// 這一步設置了lite跟full,跟前面對應起來
		//3.1 若是存在@Configuration 註解,則爲BeanDefinition 設置configurationClass屬性爲full
            if (isFullConfigurationCandidate((AnnotationMetadata)metadata)) {
                
                beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, "full");
            } else {
                // 若是AnnotationMetadata 中有 @Component, @ComponentScan, @Import, @ImportResource 註解中的任意一個,或者存在 被@bean 註解的方法,則返回true.
        // 則設置configurationClass屬性爲lite,
                if (!isLiteConfigurationCandidate((AnnotationMetadata)metadata)) {
                    return false;
                }

                beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, "lite");
            }

    // 4. 若是該類被@Order所註解,則設置order屬性爲@Order的值
            Integer order = getOrder((AnnotationMetadata)metadata);
            if (order != null) {
                beanDef.setAttribute(ORDER_ATTRIBUTE, order);
            }

            return true;
        } else {
            return false;
        }
    }    
}

複製代碼

1.3. parse開始解析,交給ConfigurationClassParser

//class : 交給ConfigurationClassParser

public void parse(Set<BeanDefinitionHolder> configCandidates) {
        Iterator var2 = configCandidates.iterator();
		
        while(var2.hasNext()) {
            BeanDefinitionHolder holder = (BeanDefinitionHolder)var2.next();
            BeanDefinition bd = holder.getBeanDefinition();
			
            try {
                if (bd instanceof AnnotatedBeanDefinition) {
                //走這裏
                    this.parse(((AnnotatedBeanDefinition)bd).getMetadata(), holder.getBeanName());
                } else if (bd instanceof AbstractBeanDefinition && ((AbstractBeanDefinition)bd).hasBeanClass()) {
                    this.parse(((AbstractBeanDefinition)bd).getBeanClass(), holder.getBeanName());
                } else {
                    this.parse(bd.getBeanClassName(), holder.getBeanName());
                }
            } catch (BeanDefinitionStoreException var6) {
                throw var6;
            } catch (Throwable var7) {
                throw new BeanDefinitionStoreException("Failed to parse configuration class [" + bd.getBeanClassName() + "]", var7);
            }
        }

        this.deferredImportSelectorHandler.process();
    }
    
    
    //metadata裏面是註解的信息
    // 這個時候確定對AnnotationMetadata不太熟悉了,AnnotationMetadata是Spring自定義的註解,它繼承了AnnotatedTypeMetadata
    // 而AnnotatedTypeMetadata是對註解元素的封裝適配,裏面內置了一些靈活可用的方法,好比getAnnotationAttributes,isAnnotated
    // getAnnotationAttributes()能夠直接判獲取一個註解中值,封裝成一個Map,isAnnotated()判斷是否存在某個註解
    // 詳細能夠參考一位大神的講解 https://fangshixiang.blog.csdn.net/article/details/88765470
    protected final void parse(AnnotationMetadata metadata, String beanName) throws IOException {
        this.processConfigurationClass(new ConfigurationClass(metadata, beanName));
    }
    // 看看ConfigurationClass的構造器
    // public ConfigurationClass(AnnotationMetadata metadata, String beanName) {
    // Assert.notNull(beanName, "Bean name must not be null");
    // this.metadata = metadata;
    // this.resource = new DescriptiveResource(metadata.getClassName());
    // this.beanName = beanName;}
    protected void processConfigurationClass(ConfigurationClass configClass) throws IOException {
        // 1.1. 判斷是否應該跳過
        if (!this.conditionEvaluator.shouldSkip(configClass.getMetadata(), ConfigurationPhase.PARSE_CONFIGURATION)) {
            // 1.2. 處理 Imported的狀況,暫時無論
            ConfigurationClass existingClass = (ConfigurationClass)this.configurationClasses.get(configClass);
            if (existingClass != null) {
                if (configClass.isImported()) {
                    if (existingClass.isImported()) {
                        existingClass.mergeImportedBy(configClass);
                    }

                    return;
                }

                this.configurationClasses.remove(configClass);
                this.knownSuperclasses.values().removeIf(configClass::equals);
            }
            // 格式如圖1.8所示
            // 那麼什麼是SourceClass 呢
            // 它是對source對象一個輕量級的包裝,持有AnnotationMetadata 元數據,以下通常實際爲一個
            // 看到裏面 SourceClass的構造器
            //public SourceClass(Object source) {
			//this.source = source;
			//if (source instanceof Class) {
			// this.metadata = new StandardAnnotationMetadata((Class<?>) source, true);
			//} else {
			// this.metadata = ((MetadataReader) source).getAnnotationMetadata();
			//}
		//}
            ConfigurationClassParser.SourceClass sourceClass = this.asSourceClass(configClass);
            do {
                //1.3. 遞歸調用進行解析,最終的解析,
                // 由於一個配置類,好比 入口類,可能會有父類,那麼這些類指定的掃描仍是得繼續進行掃描,因此遞歸調用了。
                sourceClass = this.doProcessConfigurationClass(configClass, sourceClass);
            } while(sourceClass != null);
			// 1.4. 添加到cinfigurationClasses中
            this.configurationClasses.put(configClass, configClass);
        }
    }

//1.3 遞歸調用進行解析,最終的解析
//通常狀況下一開始configClass是 入口類上的註解,也就是 @SpringbootApplication
protected final ConfigurationClassParser.SourceClass doProcessConfigurationClass(ConfigurationClass configClass, ConfigurationClassParser.SourceClass sourceClass) throws IOException {
        // 1. 處理內部類, 由於內部類的處理方式仍是跟這個方法一直的,因此咱們先忽略不看
        if (configClass.getMetadata().isAnnotated(Component.class.getName())) {
            this.processMemberClasses(configClass, sourceClass);
        }
        // 2. 處理@PropertySource,暫時看不懂
        Iterator var3 = AnnotationConfigUtils.attributesForRepeatable(sourceClass.getMetadata(), PropertySources.class, PropertySource.class).iterator();

        AnnotationAttributes importResource;
        while(var3.hasNext()) {
            importResource = (AnnotationAttributes)var3.next();
            if (this.environment instanceof ConfigurableEnvironment) {
                this.processPropertySource(importResource);
            } else {
                this.logger.info("Ignoring @PropertySource annotation on [" + sourceClass.getMetadata().getClassName() + "]. Reason: Environment must implement ConfigurableEnvironment");
            }
        }
        //3. 處理@ComponentScan
        Set<AnnotationAttributes> componentScans = AnnotationConfigUtils.attributesForRepeatable(sourceClass.getMetadata(), ComponentScans.class, ComponentScan.class);
        if (!componentScans.isEmpty() && !this.conditionEvaluator.shouldSkip(sourceClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN)) {
            Iterator var13 = componentScans.iterator();
            
            while(var13.hasNext()) {
                // 3.1 獲取該配置類@componentScan註解的信息,包裝成一個map,AnnotationAttributes繼承的就是map,
                詳細信息如圖1.9 所示
                // AnnotationAttributes是繼承一個map,裏面存放了@ComponentScan註解裏面的值。
                // 關於AnnotationMetadata 的詳細內容,後面再進行講解.
                AnnotationAttributes componentScan = (AnnotationAttributes)var13.next();
                // 3.2 交給ComponentScanParser 去解析 ,下面詳細講 parse(),大概的過程就是,獲取@ComponentScan註解掃描的路徑上的類,組裝成BeanDefinitionHolder.
                // 此時scannedBeanDefinitions大概有
                Set<BeanDefinitionHolder> scannedBeanDefinitions = this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());
                Iterator var7 = scannedBeanDefinitions.iterator();

                while(var7.hasNext()) {
                    BeanDefinitionHolder holder = (BeanDefinitionHolder)var7.next();
                    BeanDefinition bdCand = holder.getBeanDefinition().getOriginatingBeanDefinition();
                    if (bdCand == null) {
                        bdCand = holder.getBeanDefinition();
                    }
                    
                    if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) {
                        //繼續循環掃描,這個過程比較難理解
                        //就是經過1個配置類,而後發散去找到他們 @ComponentScan註解的類。
                        this.parse(bdCand.getBeanClassName(), holder.getBeanName());
                    }
                }
            }
        }
        
        this.processImports(configClass, sourceClass, this.getImports(sourceClass), true);
        importResource = AnnotationConfigUtils.attributesFor(sourceClass.getMetadata(), ImportResource.class);
        if (importResource != null) {
            String[] resources = importResource.getStringArray("locations");
            Class<? extends BeanDefinitionReader> readerClass = importResource.getClass("reader");
            String[] var19 = resources;
            int var21 = resources.length;

            for(int var22 = 0; var22 < var21; ++var22) {
                String resource = var19[var22];
                String resolvedResource = this.environment.resolveRequiredPlaceholders(resource);
                configClass.addImportedResource(resolvedResource, readerClass);
            }
        }

        Set<MethodMetadata> beanMethods = this.retrieveBeanMethodMetadata(sourceClass);
        Iterator var17 = beanMethods.iterator();

        while(var17.hasNext()) {
            MethodMetadata methodMetadata = (MethodMetadata)var17.next();
            configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
        }

        this.processInterfaces(configClass, sourceClass);
        if (sourceClass.getMetadata().hasSuperClass()) {
            String superclass = sourceClass.getMetadata().getSuperClassName();
            if (superclass != null && !superclass.startsWith("java") && !this.knownSuperclasses.containsKey(superclass)) {
                this.knownSuperclasses.put(superclass, configClass);
                // 返回父類的SourceClass,
                return sourceClass.getSuperClass();
            }
        }
        // 沒有父類,則執行結束。
        return null;
    }


}

複製代碼

圖1.8:

圖1.9

3.2 ComponentScanParser 解析掃描路徑

交給ComponentScanParser

class ComponentScanAnnotationParser {

    public Set<BeanDefinitionHolder> parse(AnnotationAttributes componentScan, final String declaringClass) {
        ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(this.registry, componentScan.getBoolean("useDefaultFilters"), this.environment, this.resourceLoader);
        Class<? extends BeanNameGenerator> generatorClass = componentScan.getClass("nameGenerator");
        boolean useInheritedGenerator = BeanNameGenerator.class == generatorClass;
        scanner.setBeanNameGenerator(useInheritedGenerator ? this.beanNameGenerator : (BeanNameGenerator)BeanUtils.instantiateClass(generatorClass));
        ScopedProxyMode scopedProxyMode = (ScopedProxyMode)componentScan.getEnum("scopedProxy");
        if (scopedProxyMode != ScopedProxyMode.DEFAULT) {
            scanner.setScopedProxyMode(scopedProxyMode);
        } else {
            Class<? extends ScopeMetadataResolver> resolverClass = componentScan.getClass("scopeResolver");
            scanner.setScopeMetadataResolver((ScopeMetadataResolver)BeanUtils.instantiateClass(resolverClass));
        }

        scanner.setResourcePattern(componentScan.getString("resourcePattern"));
        AnnotationAttributes[] var15 = componentScan.getAnnotationArray("includeFilters");
        int var8 = var15.length;

        int var9;
        AnnotationAttributes filter;
        Iterator var11;
        TypeFilter typeFilter;
        for(var9 = 0; var9 < var8; ++var9) {
            filter = var15[var9];
            var11 = this.typeFiltersFor(filter).iterator();

            while(var11.hasNext()) {
                typeFilter = (TypeFilter)var11.next();
                scanner.addIncludeFilter(typeFilter);
            }
        }

        var15 = componentScan.getAnnotationArray("excludeFilters");
        var8 = var15.length;

        for(var9 = 0; var9 < var8; ++var9) {
            filter = var15[var9];
            var11 = this.typeFiltersFor(filter).iterator();

            while(var11.hasNext()) {
                typeFilter = (TypeFilter)var11.next();
                scanner.addExcludeFilter(typeFilter);
            }
        }

        boolean lazyInit = componentScan.getBoolean("lazyInit");
        if (lazyInit) {
            scanner.getBeanDefinitionDefaults().setLazyInit(true);
        }

        Set<String> basePackages = new LinkedHashSet();
        String[] basePackagesArray = componentScan.getStringArray("basePackages");
        String[] var19 = basePackagesArray;
        int var21 = basePackagesArray.length;

        int var22;
        for(var22 = 0; var22 < var21; ++var22) {
            String pkg = var19[var22];
            String[] tokenized = StringUtils.tokenizeToStringArray(this.environment.resolvePlaceholders(pkg), ",; \t\n");
            Collections.addAll(basePackages, tokenized);
        }

        Class[] var20 = componentScan.getClassArray("basePackageClasses");
        var21 = var20.length;

        for(var22 = 0; var22 < var21; ++var22) {
            Class<?> clazz = var20[var22];
            basePackages.add(ClassUtils.getPackageName(clazz));
        }

        if (basePackages.isEmpty()) {
            basePackages.add(ClassUtils.getPackageName(declaringClass));
        }

        scanner.addExcludeFilter(new AbstractTypeHierarchyTraversingFilter(false, false) {
            protected boolean matchClassName(String className) {
                return declaringClass.equals(className);
            }
        });
        // 這是真正的解析方法,這裏的
         // basePackages = "**.**.**" //通常是 @ComponentScan(basePackages = "**") 
         // 掃描這個路徑下面全部的包以及包下面的內容
        return scanner.doScan(StringUtils.toStringArray(basePackages));
    }
    
}

  // 掃描這個路徑下面全部的包以及包下面的內容
    protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
        Assert.notEmpty(basePackages, "At least one base package must be specified");
        Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet();
        String[] var3 = basePackages;
        int var4 = basePackages.length;

        for(int var5 = 0; var5 < var4; ++var5) {
            String basePackage = var3[var5];
            // 這個方法是最重點,把掃描到的Bean就放進來了(好比此處只有RootConfig一個Bean定義,是個配置類)
			// 3.2.1 這個是重點,會把該包下面全部的Bean都掃描進去。Spring5和一下的處理方式不同哦~
			// 下面有講解
            Set<BeanDefinition> candidates = this.findCandidateComponents(basePackage);
            Iterator var8 = candidates.iterator();
			// 開始遍歷掃描到得全部的類
            while(var8.hasNext()) {
                BeanDefinition candidate = (BeanDefinition)var8.next();
                ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);
                // 設置其 scope, 單例仍是多例
                candidate.setScope(scopeMetadata.getScopeName());
                String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);
                // // 此處爲掃描的Bean,爲ScannedGenericBeanDefinition,因此確定爲true
				// 所以進來,執行postProcessBeanDefinition(對Bean定義信息作) 以下詳解
				// 注意:只是添加些默認的Bean定義信息,並非執行後置處理器~~~
				// 3.2.2 
                if (candidate instanceof AbstractBeanDefinition) {
                    this.postProcessBeanDefinition((AbstractBeanDefinition)candidate, beanName);		
                }
                // 顯然,此處也是true 也是完善好比Bean上的一些註解信息:好比@Lazy、@Primary、@DependsOn、@Role、@Description 大概的操做方式是
                abd.setDependsOn(dependsOn.getStringArray("value"));
                @Role註解用於Bean的分類分組,沒有太大的做用
                if (candidate instanceof AnnotatedBeanDefinition) {
                    AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition)candidate);
                }
				// 檢查這個Bean 好比
				//若是dao包(通常配置的basePakage是這個)下的類是符合mybaits要求的則向spring IOC容器中註冊它的BeanDefinition 因此這步檢查第三方Bean的時候有必要檢查一下
                if (this.checkCandidate(beanName, candidate)) {
                    BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
                    //AnnotationConfigUtils類的applyScopedProxyMode方法根據註解Bean定義類中配置的做用域@Scope註解的值,爲Bean定義應用相應的代理模式,主要是在Spring面向切面編程(AOP)中使用
                    definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);		
                    beanDefinitions.add(definitionHolder);
                    // 在GenericApplicationContext中執行this.aliasMap.put(alias, name);
                    // this.beanDefinitionMap.put(beanName, beanDefinition)
                    // 在這裏把類BeanDefinitionHolder加載進 容器中的
                    this.registerBeanDefinition(definitionHolder, this.registry);
                }
            }
        }
        // 
        return beanDefinitions;
    }


  // 3.2.1 解析 掃描 RootConfig
    public Set<BeanDefinition> findCandidateComponents(String basePackage) {
		// 上面說過了CandidateComponentsIndex是Spring5提供的優化掃描的功能
		// 顯然這裏編譯器咱們沒有寫META-INF/spring.components索引文件,因此此處不會執行Spring5 的掃描方式,因此我暫時不看了(超大型項目纔會使用Spring5的方式)
		if (this.componentsIndex != null && indexSupportsIncludeFilters()) {
			return addCandidateComponentsFromIndex(this.componentsIndex, basePackage);
		} else {
			// Spring 5以前的方式(絕大多數狀況下,都是此方式)
			return scanCandidateComponents(basePackage);
		}
	}


     private Set<BeanDefinition> scanCandidateComponents(String basePackage) {
        LinkedHashSet candidates = new LinkedHashSet();
		// classpath*:com/macro/mall/**/*.class
        // resourcePatter是 **/*.class
        // componentScan中就有指定了resourcePatter的內容是 "**/*.class"
        try {
            String packageSearchPath = "classpath*:" + this.resolveBasePackage(basePackage) + '/' + this.resourcePattern;
            //getResourcePatternResolver獲取獲得的是 PathMatchingResourcePatternResolver
            // 10.1.1 進行講解
            Resource[] resources = this.getResourcePatternResolver().getResources(packageSearchPath);
            // 記錄日誌(下面我把打印日誌地方都刪除)
            boolean traceEnabled = this.logger.isTraceEnabled();
            boolean debugEnabled = this.logger.isDebugEnabled();
            Resource[] var7 = resources;
            int var8 = resources.length;
			// 接下來的這個for循環:就是把一個個的resource組裝成ScannedGenericBeanDefinition
            for(int var9 = 0; var9 < var8; ++var9) {
                Resource resource = var7[var9];
                //文件必須可讀 不然直接返回空了
                
                if (traceEnabled) {
                    this.logger.trace("Scanning " + resource);
                }
				// 要是可讀的
                if (resource.isReadable()) {
                    try {
                        MetadataReader metadataReader = this.getMetadataReaderFactory().getMetadataReader(resource);
                        //// 根據TypeFilter過濾排除組件。由於AppConfig沒有標準@Component或者子註解,因此確定不屬於候選組件 返回false
						// 注意:這裏通常(默認處理的狀況下)標註了默認註解的纔會true,什麼叫默認註解呢?就是@Component或者派生註解。還有javax....的,這裏省略啦

                        if (this.isCandidateComponent(metadataReader)) {
                            // 
                            ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader);
                            sbd.setResource(resource);
                            sbd.setSource(resource);
                            if (this.isCandidateComponent((AnnotatedBeanDefinition)sbd)) {
                                if (debugEnabled) {
                                    this.logger.debug("Identified candidate component class: " + resource);
                                }

                                candidates.add(sbd);
                            } else if (debugEnabled) {
                                this.logger.debug("Ignored because not a concrete top-level class: " + resource);
                            }
                        } else if (traceEnabled) {
                            this.logger.trace("Ignored because not matching any filter: " + resource);
                        }
                    } catch (Throwable var13) {
                        throw new BeanDefinitionStoreException("Failed to read candidate component class: " + resource, var13);
                    }
                } else if (traceEnabled) {
                    this.logger.trace("Ignored because not readable: " + resource);
                }
            }

            return candidates;
        } catch (IOException var14) {
            throw new BeanDefinitionStoreException("I/O failure during classpath scanning", var14);
        }
    }
    
    
    
    //10.1.1 講解, 獲取掃描路徑下全部 ** 的類
public class PathMatchingResourcePatternResolver implements ResourcePatternResolver {
    // 好比此時locationPattern是 "classpath: com/**/**/**/*.class" 
    protected Resource[] findPathMatchingResources(String locationPattern) throws IOException {
        // 此時的rootDirPath 是 com/**/**/
        String rootDirPath = this.determineRootDir(
);		
        // 此時的subPattern是 **/*.class
        String subPattern = locationPattern.substring(rootDirPath.length());
        // 這個方法在下面 10.1.1.1 解析
        // 獲得的結果是 URLResource,裏面是 URL url + String name
        // 這裏獲得的URL內容是: file:/D:/project/mall/mall-admin/target/classes/com/macro/mall/], target裏面的內容
        Resource[] rootDirResources = this.getResources(rootDirPath);
        Set<Resource> result = new LinkedHashSet(16);
        Resource[] var6 = rootDirResources;
        int var7 = rootDirResources.length;

        for(int var8 = 0; var8 < var7; ++var8) {
            Resource rootDirResource = var6[var8];
            Resource rootDirResource = this.resolveRootDirResource(rootDirResource);
            URL rootDirUrl = ((Resource)rootDirResource).getURL();
            if (equinoxResolveMethod != null && rootDirUrl.getProtocol().startsWith("bundle")) {
                URL resolvedUrl = (URL)ReflectionUtils.invokeMethod(equinoxResolveMethod, (Object)null, new Object[]{rootDirUrl});
                if (resolvedUrl != null) {
                    rootDirUrl = resolvedUrl;
                }

                rootDirResource = new UrlResource(rootDirUrl);
            }

            if (rootDirUrl.getProtocol().startsWith("vfs")) {
                result.addAll(PathMatchingResourcePatternResolver.VfsResourceMatchingDelegate.findMatchingResources(rootDirUrl, subPattern, this.getPathMatcher()));
            } else if (!ResourceUtils.isJarURL(rootDirUrl) && !this.isJarResource((Resource)rootDirResource)) {
               //doFindPathMatchingFileResources直接走這裏,由於是文件的資源,不是jar包等,此時的 subPattern是「 **/*.class 」,因此邏輯是,獲得掃描rootDirResource,全部匹配subPattern(**/*.class)的類
                result.addAll(this.doFindPathMatchingFileResources((Resource)rootDirResource, subPattern));
            } else {
                result.addAll(this.doFindPathMatchingJarResources((Resource)rootDirResource, rootDirUrl, subPattern));
            }
        }

        if (logger.isTraceEnabled()) {
            logger.trace("Resolved location pattern [" + locationPattern + "] to resources " + result);
        }

        return (Resource[])result.toArray(new Resource[0]);
    }
    
    // 10.1.1.1 根據基路徑 ,掃描其下全部資源
    public Resource[] getResources(String locationPattern) throws IOException {
        Assert.notNull(locationPattern, "Location pattern must not be null");
        if (locationPattern.startsWith("classpath*:")) {
            return 
                //直接看這一步findPathMatchingResources()
                this.getPathMatcher().isPattern(locationPattern.substring("classpath*:".length())) ? this.findPathMatchingResources(locationPattern) : this.findAllClassPathResources(locationPattern.substring("classpath*:".length()));
        } else {
            int prefixEnd = locationPattern.startsWith("war:") ? locationPattern.indexOf("*/") + 1 : locationPattern.indexOf(58) + 1;
            return this.getPathMatcher().isPattern(locationPattern.substring(prefixEnd)) ? this.findPathMatchingResources(locationPattern) : new Resource[]{this.getResourceLoader().getResource(locationPattern)};
        }
    }
	 //location 是 "/com/**/**"
    protected Resource[] findAllClassPathResources(String location) throws IOException {
        String path = location;
        if (location.startsWith("/")) {
            path = location.substring(1);
        }
		//直接看這裏
        Set<Resource> result = this.doFindAllClassPathResources(path);
        if (logger.isTraceEnabled()) {
            logger.trace("Resolved classpath location [" + location + "] to resources " + result);
        }

        return (Resource[])result.toArray(new Resource[0]);
    }
    // 獲得的結果是URLResource [file:/D:/project/mall/mall-admin/target/classes/com/macro/mall/]
    protected Set<Resource> doFindAllClassPathResources(String path) throws IOException {
        Set<Resource> result = new LinkedHashSet(16);
        ClassLoader cl = this.getClassLoader();
        Enumeration resourceUrls = cl != null ? cl.getResources(path) : ClassLoader.getSystemResources(path);

        while(resourceUrls.hasMoreElements()) {
            URL url = (URL)resourceUrls.nextElement();
            result.add(this.convertClassLoaderURL(url));
        }

        if ("".equals(path)) {
            this.addAllClassLoaderJarRoots(cl, result);
        }

        return result;
    }
    
}
複製代碼

總結

從目錄中能夠看到,

  • (1) 一開始是設置配置環境、監聽器等
  • (2)以後是建立DefaultListableBeanFactory -(3)接下來是執行beanFactoryPostProcessor,其中涉及到建立配置類的過程,交給了ConfigurationClassParser和ClassPathBeanDefinitionScanner去掃描循環解析。

參考連接 小家Spring 2 3 4 5

下期預告

仍是繼續講解refresh()的剩餘內容

相關文章
相關標籤/搜索