走心Springboot源码解析: 四、refresh方法

打个广告

个人想写《springboot源码解析》这一系列很久了,但是一直角儿心底的知识积累不足,所以一直没有动笔。
所以想找一些小伙伴一起写这一系列,互相纠错交流学习。
如果有小伙伴有兴趣一起把这一系列的讲解写完的话,加下我微信:13670426148,我们一起完成,当交流学习。
后期还想写一系列介绍rpc框架的,不过要再过一阵子了,先把springboot的写完

前言

直接讲了 refresh() 的代码实现,直到完成配置类的实例化为止,后面的registerBeanPostProcessors方法还没开始讲。

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 :
走心Springboot源码解析: 四、refresh方法

2. 创建新的beanFactory

两步,第一步创建新的beanFactory,第二步是进行基本的配置

1.创建新的beanFacotry,实际创建的为DefaultListableBeanFactory

protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
        //在application中创建DefaultListableBeanFactory并赋值给上下文中的this.beanFactory,相当于原先那个不要了,创建一个新的.
        this.refreshBeanFactory();
        return this.getBeanFactory();
}

其中refreshBeanFactory()方法是通过 GenericApplicationContext来执行的这个

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:
走心Springboot源码解析: 四、refresh方法

DefaultListableBeanFactory 中存在的是
beanDefinitionMapresolvableDependenciesbeanDefinitionNamesmanualSingletonNames

beanDefinitionNames记录了创建了的beanDefinition的类型集合,beanDefinitionMap存放的是beanDefinition映射。迄今为止已经存在的有:
图1.3
走心Springboot源码解析: 四、refresh方法

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:

走心Springboot源码解析: 四、refresh方法

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:
走心Springboot源码解析: 四、refresh方法

//重点 : 开始解析配置类信息
解释一下,先找到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:
走心Springboot源码解析: 四、refresh方法

图1.9

走心Springboot源码解析: 四、refresh方法

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()的剩余内容

上一篇:android – 无法从List中刷新Listview


下一篇:如何强制刷新wx.Panel?