java复习笔记3--SpringCloud系列一:微服务启动原理探索之beanFactory加载

昨天,我们对SpringApplication的初始化以及SpringApplication.run方法中的部分代码进行了解读和追踪。这一块的重点就是Spring的 SPI,META-INF/spring.factories文件的格式以及加载机制。一定要花时间去研读这块的代码,spring的初始化基本都会用这个方法去注入,其次就是java.awt.headless模式以及用途,其他的属性注入就不做过多解释了。
今天,主要是将剩下的流程走完,尤其是昨天提到的,refreshContext这个方法,涉及东西较多,今天会重点研读这个。
首先,refreshContext方法主要是调用AbstractApplicationContext的refresh方法,先上一段源码:

 public void refresh() throws BeansException, IllegalStateException {
        Object var1 = this.startupShutdownMonitor;
        synchronized(this.startupShutdownMonitor) {
            this.prepareRefresh();
            ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();
            this.prepareBeanFactory(beanFactory);

            try {
                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();
            }

        }
    }

同步锁

第一眼就能看见整个synchronized关键字,说明方法是同步加锁的,为了防止重复注入属性或者实例化,这里使用的是moniter对象。而没有直接在方法上加锁,也是为了和其他方法进行同步加锁,比如后面的close方法和destroy以及registerShutdownHook。针对于锁和线程安全,之后会花大量时间去温习。

设置此次刷新applicationContext上下文的状态

prepareRefresh主要就是设置上下文刷新状态

初始化beanFactory

 ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();
            this.prepareBeanFactory(beanFactory);

这两行代码主要是对ApplicationContex中的beanFactory进行实例化和属性赋值。将ApplicationContex中的属性赋值给beanFactory容器中,比如classLoader,装配规则,bean的后置加载器。其实就是解析注入bean所需要的一些依赖。

bean的装配

invokeBeanFactoryPostProcessors这个步骤是整个最核心的部分,也是最繁琐的部分。我们先贴一下源码:

public static void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {
        Set<String> processedBeans = new HashSet();
        ArrayList regularPostProcessors;
        ArrayList registryProcessors;
        int var9;
        ArrayList currentRegistryProcessors;
        String[] postProcessorNames;
        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();
                if(postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
                    BeanDefinitionRegistryPostProcessor registryProcessor = (BeanDefinitionRegistryPostProcessor)postProcessor;
                    registryProcessor.postProcessBeanDefinitionRegistry(registry);
                    registryProcessors.add(registryProcessor);
                } else {
                    regularPostProcessors.add(postProcessor);
                }
            }

            currentRegistryProcessors = new ArrayList();
            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.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
                    processedBeans.add(ppName);
                }
            }

            sortPostProcessors(currentRegistryProcessors, beanFactory);
            registryProcessors.addAll(currentRegistryProcessors);
            invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
            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();
    }

昨天,说到了,prepareContext这个方法初始化context的容器的时候,注入了三个beanFactoryPostProcessor。BeanFactoryPostProcessor在容器实例化任何bean之前读取bean的定义(配置元数据),并可以修改它。同时可以定义多个BeanFactoryPostProcessor,通过设置getOrder返回值来确定各个BeanFactoryPostProcessor执行顺序。这样spring有很好的拓展性
在这里插入图片描述

回到上面的代码,成员变量就是用来防止重复注入或者重复调用BeanFactoryPostProcessor的,然后, if(beanFactory instanceof BeanDefinitionRegistry) 这里就是判断beanFactory 是否继承于BeanDefinitionRegistry的,如果是,就遍历之前注入到context中的所有的BeanFactoryPostProcessor。调用他们的postProcessBeanDefinitionRegistry这个方法。
遍历完成之后,currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));这个方法就是注入了ConfigurationClassPostProcessor,这个方法是扫描并创建bean,实例化到Spring上下文容器中最重要的一个类。

bean的解析过程 parser

       //注入ConfigurationClassPostProcessor
          registryProcessors.addAll(currentRegistryProcessors);
              //激活,即调用ConfigurationClassPostProcessor中的postProcessBeanDefinitionRegistry方法
            invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);

ConfigurationClassPostProcessor中的postProcessBeanDefinitionRegistry方法是解析和装配bean的核心,先上一下源码:

public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
        List<BeanDefinitionHolder> configCandidates = new ArrayList();
         // 1. 获取已经注册的bean名称
        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);
            if(!ConfigurationClassUtils.isFullConfigurationClass(beanDef) && !ConfigurationClassUtils.isLiteConfigurationClass(beanDef)) {
                if(ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) {
                // 1.1. 判断对应bean是否为配置类,如果是,则加入到configCandidates
                    configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));
                }
            } else if(this.logger.isDebugEnabled()) {
             // 1.2. 如果BeanDefinition 中的configurationClass 属性为full 或者lite ,则意味着已经处理过了,直接跳过
                this.logger.debug("Bean definition has already been processed as a configuration class: " + beanDef);
            }
        }

 // 1.3 如果存在配置类,进行排序
        if(!configCandidates.isEmpty()) {
            configCandidates.sort((bd1, bd2) -> {
                int i1 = ConfigurationClassUtils.getOrder(bd1.getBeanDefinition());
                int i2 = ConfigurationClassUtils.getOrder(bd2.getBeanDefinition());
                return Integer.compare(i1, i2);
            });
            SingletonBeanRegistry sbr = null;
            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;
                    }
                }
            }

            if(this.environment == null) {
                this.environment = new StandardEnvironment();
            }
           //1.4. 实例化ConfigurationClassParser 为了解析 各个配置类
            ConfigurationClassParser parser = new ConfigurationClassParser(this.metadataReaderFactory, this.problemReporter, this.environment, this.resourceLoader, this.componentScanBeanNameGenerator, registry);
            //1.5 去重
            Set<BeanDefinitionHolder> candidates = new LinkedHashSet(configCandidates);
            HashSet alreadyParsed = new HashSet(configCandidates.size());

            do {
            //1.6进行解析调用的方法
                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());
                }

                this.reader.loadBeanDefinitions(configClasses);
                alreadyParsed.addAll(configClasses);
                candidates.clear();
                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();
            }

        }
    }

先大致分析,了解一下这个方法的思路。首先,遍历所有的已经注册的bean名称,判断对应bean是否为配置文件bean(包含Configuration注解),加入configCandidates中后,然后对他们按照order进行排序。然后实例化ConfigurationClassParser 为了解析各个配置类.实例化2个set,candidates 用于将之前加入的configCandidates 进行去重,alreadyParsed 用于判断是否处理过。再调用ConfigurationClassParser#parse进行解析。而进去发现最终调用的是ConfigurationClassParser#processConfigurationClass

 protected void processConfigurationClass(ConfigurationClass configClass) throws IOException {
        if(!this.conditionEvaluator.shouldSkip(configClass.getMetadata(), ConfigurationPhase.PARSE_CONFIGURATION)) {
            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);
            }

            ConfigurationClassParser.SourceClass sourceClass = this.asSourceClass(configClass);

            do {
                sourceClass = this.doProcessConfigurationClass(configClass, sourceClass);
            } while(sourceClass != null);

            this.configurationClasses.put(configClass, configClass);
        }
    }

首先判断该bean是否被跳过,然后对Class进行包装,调用sourceClass = doProcessConfigurationClass(configClass,sourceClass)处理Application类。

@Nullable
    protected final ConfigurationClassParser.SourceClass doProcessConfigurationClass(ConfigurationClass configClass, ConfigurationClassParser.SourceClass sourceClass) throws IOException {
        this.processMemberClasses(configClass, sourceClass);
        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.warn("Ignoring @PropertySource annotation on [" + sourceClass.getMetadata().getClassName() + "]. Reason: Environment must implement ConfigurableEnvironment");
            }
        }

        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()) {
                AnnotationAttributes componentScan = (AnnotationAttributes)var13.next();
                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)) {
                        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);
                return sourceClass.getSuperClass();
            }
        }

        return null;
    }

核心方法就是this.processPropertySource(importResource);

扫描二维码关注公众号,回复: 3994592 查看本文章
 private void processPropertySource(AnnotationAttributes propertySource) throws IOException {
        String name = propertySource.getString("name");
        if(!StringUtils.hasLength(name)) {
            name = null;
        }

        String encoding = propertySource.getString("encoding");
        if(!StringUtils.hasLength(encoding)) {
            encoding = null;
        }

        String[] locations = propertySource.getStringArray("value");
        Assert.isTrue(locations.length > 0, "At least one @PropertySource(value) location is required");
        boolean ignoreResourceNotFound = propertySource.getBoolean("ignoreResourceNotFound");
        Class<? extends PropertySourceFactory> factoryClass = propertySource.getClass("factory");
        PropertySourceFactory factory = factoryClass == PropertySourceFactory.class?DEFAULT_PROPERTY_SOURCE_FACTORY:(PropertySourceFactory)BeanUtils.instantiateClass(factoryClass);
        String[] var8 = locations;
        int var9 = locations.length;

        for(int var10 = 0; var10 < var9; ++var10) {
            String location = var8[var10];

            try {
                String resolvedLocation = this.environment.resolveRequiredPlaceholders(location);
                Resource resource = this.resourceLoader.getResource(resolvedLocation);
                this.addPropertySource(factory.createPropertySource(name, new EncodedResource(resource, encoding)));
            } catch (FileNotFoundException | UnknownHostException | IllegalArgumentException var14) {
                if(!ignoreResourceNotFound) {
                    throw var14;
                }

                if(this.logger.isInfoEnabled()) {
                    this.logger.info("Properties location [" + location + "] not resolvable: " + var14.getMessage());
                }
            }
        }

    }

通过注解中的信息获取资源信息,然后添加到MutablePropertySourcespropertySources = ((ConfigurableEnvironment)this.environment).getPropertySources()中。之后就是解析扫描ComponentScan。Set componentScans = AnnotationConfigUtils.attributesForRepeatable(sourceClass.getMetadata(), ComponentScans.class, ComponentScan.class);之后,就是获取资源路径,在获取到path路径以后spring采用类加载器获取指定Class文件对应的资源信息,根据不同的元数据,进行不同的解析。
至此,整个流程基本结束了,由于东西较多,自己看着也比较迷糊,先大致过一遍,应该漏了许多细节,大家可以提出来一起讨论,之后对于这块,会继续花时间走读代码,再做一个详细的说明,并会结合自己的代码去说明流程了项目中应用。

猜你喜欢

转载自blog.csdn.net/aizhupo1314/article/details/83687597