zoukankan      html  css  js  c++  java
  • 走心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 :

    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:

    DefaultListableBeanFactory 中存在的是
    beanDefinitionMapresolvableDependenciesbeanDefinitionNamesmanualSingletonNames

    beanDefinitionNames记录了创建了的beanDefinition的类型集合,beanDefinitionMap存放的是beanDefinition映射。迄今为止已经存在的有:
    图1.3

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

  • 相关阅读:
    html 简介
    MySQL事务等了解知识
    MySQL—navicat&&练习&&pymysql
    MySQL查询表(一)
    作业
    MySQL约束&&表关系
    mysql数据类型
    初识mysql
    dll 原理解析
    又过了一天
  • 原文地址:https://www.cnblogs.com/disandafeier/p/12081301.html
Copyright © 2011-2022 走看看