美文网首页
springboot源码4--bean加载

springboot源码4--bean加载

作者: xian_cheng | 来源:发表于2018-11-22 00:16 被阅读0次

    这一节首先研究bean加载,bean加载主要是将项目中的bean扫描加入到DefaultListableBeanFactory中的beanDefinitionMap中,下面就看下怎么实现的。

    1. bean加载

        @Override
        public void refresh() throws BeansException, IllegalStateException {
            synchronized (this.startupShutdownMonitor) {
                。。。
    
                try {
                    。。。
                    invokeBeanFactoryPostProcessors(beanFactory);
    
                    。。。。
    
                    // Instantiate all remaining (non-lazy-init) singletons.
                    finishBeanFactoryInitialization(beanFactory);
                                    。。。。
                }
    
                catch (BeansException ex) {
                }
                finally {
                }
            }
        }
    

    bean的加载是在invokeBeanFactoryPostProcessors这个方法中完成,进入这个方法看下。

        protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
            PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
    
            // Detect a LoadTimeWeaver and prepare for weaving, if found in the meantime
            // (e.g. through an @Bean method registered by ConfigurationClassPostProcessor)
            if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
                beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
                beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
            }
        }
    

    进入PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors方法。

        public static void invokeBeanFactoryPostProcessors(
                ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {
    
            // Invoke BeanDefinitionRegistryPostProcessors first, if any.
            Set<String> processedBeans = new HashSet<String>();
    
            if (beanFactory instanceof BeanDefinitionRegistry) {
                BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
                List<BeanFactoryPostProcessor> regularPostProcessors = new LinkedList<BeanFactoryPostProcessor>();
                List<BeanDefinitionRegistryPostProcessor> registryPostProcessors =
                        new LinkedList<BeanDefinitionRegistryPostProcessor>();
    
                for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
                    if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
                        BeanDefinitionRegistryPostProcessor registryPostProcessor =
                                (BeanDefinitionRegistryPostProcessor) postProcessor;
                        registryPostProcessor.postProcessBeanDefinitionRegistry(registry);
                        registryPostProcessors.add(registryPostProcessor);
                    }
                    else {
                        regularPostProcessors.add(postProcessor);
                    }
                }
    
                // Do not initialize FactoryBeans here: We need to leave all regular beans
                // uninitialized to let the bean factory post-processors apply to them!
                // Separate between BeanDefinitionRegistryPostProcessors that implement
                // PriorityOrdered, Ordered, and the rest.
                String[] postProcessorNames =
                        beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
    
                // First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered.
                List<BeanDefinitionRegistryPostProcessor> priorityOrderedPostProcessors = new ArrayList<BeanDefinitionRegistryPostProcessor>();
                for (String ppName : postProcessorNames) {
                    if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
                        priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
                        processedBeans.add(ppName);
                    }
                }
                sortPostProcessors(beanFactory, priorityOrderedPostProcessors);
                registryPostProcessors.addAll(priorityOrderedPostProcessors);
                invokeBeanDefinitionRegistryPostProcessors(priorityOrderedPostProcessors, registry);
    
                // Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered.
                postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
                List<BeanDefinitionRegistryPostProcessor> orderedPostProcessors = new ArrayList<BeanDefinitionRegistryPostProcessor>();
                for (String ppName : postProcessorNames) {
                    if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {
                        orderedPostProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
                        processedBeans.add(ppName);
                    }
                }
                sortPostProcessors(beanFactory, orderedPostProcessors);
                registryPostProcessors.addAll(orderedPostProcessors);
                invokeBeanDefinitionRegistryPostProcessors(orderedPostProcessors, registry);
    
                // Finally, invoke all other BeanDefinitionRegistryPostProcessors until no further ones appear.
                boolean reiterate = true;
                while (reiterate) {
                    reiterate = false;
                    postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
                    for (String ppName : postProcessorNames) {
                        if (!processedBeans.contains(ppName)) {
                            BeanDefinitionRegistryPostProcessor pp = beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class);
                            registryPostProcessors.add(pp);
                            processedBeans.add(ppName);
                            pp.postProcessBeanDefinitionRegistry(registry);
                            reiterate = true;
                        }
                    }
                }
    
                // Now, invoke the postProcessBeanFactory callback of all processors handled so far.
                invokeBeanFactoryPostProcessors(registryPostProcessors, beanFactory);
                invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
            }
    
            else {
                // Invoke factory processors registered with the context instance.
                invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
            }
    
            // Do not initialize FactoryBeans here: We need to leave all regular beans
            // uninitialized to let the bean factory post-processors apply to them!
            String[] postProcessorNames =
                    beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);
    
            // Separate between BeanFactoryPostProcessors that implement PriorityOrdered,
            // Ordered, and the rest.
            List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<BeanFactoryPostProcessor>();
            List<String> orderedPostProcessorNames = new ArrayList<String>();
            List<String> nonOrderedPostProcessorNames = new ArrayList<String>();
            for (String ppName : postProcessorNames) {
                if (processedBeans.contains(ppName)) {
                    // skip - already processed in first phase above
                }
                else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
                    priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
                }
                else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
                    orderedPostProcessorNames.add(ppName);
                }
                else {
                    nonOrderedPostProcessorNames.add(ppName);
                }
            }
    
            // First, invoke the BeanFactoryPostProcessors that implement PriorityOrdered.
            sortPostProcessors(beanFactory, priorityOrderedPostProcessors);
            invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);
    
            // Next, invoke the BeanFactoryPostProcessors that implement Ordered.
            List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<BeanFactoryPostProcessor>();
            for (String postProcessorName : orderedPostProcessorNames) {
                orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
            }
            sortPostProcessors(beanFactory, orderedPostProcessors);
            invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);
    
            // Finally, invoke all other BeanFactoryPostProcessors.
            List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<BeanFactoryPostProcessor>();
            for (String postProcessorName : nonOrderedPostProcessorNames) {
                nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
            }
            invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);
    
            // Clear cached merged bean definitions since the post-processors might have
            // modified the original metadata, e.g. replacing placeholders in values...
            beanFactory.clearMetadataCache();
        }
    

    这个方法特别长,一步一步来分析吧。

    1.1 遍历beanFactoryPostProcessors

    beanFactoryPostProcessors的作用就是修改已经注册的bean定义,这里的beanFactoryPostProcessors主要有下面三个:
    ConfigurationWarningPostProcessor
    CachingMetadataReaderFactoryPostProcessor
    PropertySourceOrderingPostProcessor
    这三个beanFactoryPostProcessor分别是在ConfigurationWarningsApplicationContextInitializer 、SharedMetadataReaderFactoryContextInitializer 、ConfigFileApplicationListener初始化器中的initialize方法中添加的。

    1.2 按照优先级顺序优先执行PriorityOrdered接口的BeanDefinitionRegistryPostProcessor实现类。

    首先利用beanFactory.getBeanNamesForType方法从beanDefinitionMap获取所有BeanDefinitionRegistryPostProcessor的实现类,然后遍历这些实现类找到实现PriorityOrdered接口的实现类,放入priorityOrderedPostProcessors这个list集合中,对这个集合排序,最后调用invokeBeanDefinitionRegistryPostProcessors方法触发这些BeanDefinitionRegistryPostProcessor实现类的执行。
    看下invokeBeanDefinitionRegistryPostProcessors这个方法的实现。

        private static void invokeBeanDefinitionRegistryPostProcessors(
                Collection<? extends BeanDefinitionRegistryPostProcessor> postProcessors, BeanDefinitionRegistry registry) {
    
            for (BeanDefinitionRegistryPostProcessor postProcessor : postProcessors) {
                postProcessor.postProcessBeanDefinitionRegistry(registry);
            }
        }
    

    这个方法遍历执行BeanDefinitionRegistryPostProcessor 中的postProcessBeanDefinitionRegistry方法,这里的BeanDefinitionRegistryPostProcessor 实现类其实就一个是ConfigurationClassPostProcessor这个类。那么接下来就看下这个类的postProcessBeanDefinitionRegistry方法的实现。

        @Override
        public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
            。。。。
            processConfigBeanDefinitions(registry);
        }
    
        public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
            List<BeanDefinitionHolder> configCandidates = new ArrayList<BeanDefinitionHolder>();
            String[] candidateNames = registry.getBeanDefinitionNames();
    
            for (String beanName : candidateNames) {
                BeanDefinition beanDef = registry.getBeanDefinition(beanName);
                if (ConfigurationClassUtils.isFullConfigurationClass(beanDef) ||
                        ConfigurationClassUtils.isLiteConfigurationClass(beanDef)) {
                    if (logger.isDebugEnabled()) {
                        logger.debug("Bean definition has already been processed as a configuration class: " + beanDef);
                    }
                }
                else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) {
                    configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));
                }
            }
    
            // Return immediately if no @Configuration classes were found
            if (configCandidates.isEmpty()) {
                return;
            }
    
            // Sort by previously determined @Order value, if applicable
            Collections.sort(configCandidates, new Comparator<BeanDefinitionHolder>() {
                @Override
                public int compare(BeanDefinitionHolder bd1, BeanDefinitionHolder bd2) {
                    int i1 = ConfigurationClassUtils.getOrder(bd1.getBeanDefinition());
                    int i2 = ConfigurationClassUtils.getOrder(bd2.getBeanDefinition());
                    return (i1 < i2) ? -1 : (i1 > i2) ? 1 : 0;
                }
            });
    
            // Detect any custom bean name generation strategy supplied through the enclosing application context
            SingletonBeanRegistry sbr = null;
            if (registry instanceof SingletonBeanRegistry) {
                sbr = (SingletonBeanRegistry) registry;
                if (!this.localBeanNameGeneratorSet && sbr.containsSingleton(CONFIGURATION_BEAN_NAME_GENERATOR)) {
                    BeanNameGenerator generator = (BeanNameGenerator) sbr.getSingleton(CONFIGURATION_BEAN_NAME_GENERATOR);
                    this.componentScanBeanNameGenerator = generator;
                    this.importBeanNameGenerator = generator;
                }
            }
    
            // Parse each @Configuration class
            ConfigurationClassParser parser = new ConfigurationClassParser(
                    this.metadataReaderFactory, this.problemReporter, this.environment,
                    this.resourceLoader, this.componentScanBeanNameGenerator, registry);
    
            Set<BeanDefinitionHolder> candidates = new LinkedHashSet<BeanDefinitionHolder>(configCandidates);
            Set<ConfigurationClass> alreadyParsed = new HashSet<ConfigurationClass>(configCandidates.size());
            do {
                parser.parse(candidates);
                parser.validate();
    
                Set<ConfigurationClass> configClasses = new LinkedHashSet<ConfigurationClass>(parser.getConfigurationClasses());
                configClasses.removeAll(alreadyParsed);
    
                // Read the model and create bean definitions based on its content
                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<String>(Arrays.asList(candidateNames));
                    Set<String> alreadyParsedClasses = new HashSet<String>();
                    for (ConfigurationClass configurationClass : alreadyParsed) {
                        alreadyParsedClasses.add(configurationClass.getMetadata().getClassName());
                    }
                    for (String candidateName : newCandidateNames) {
                        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());
    
            // Register the ImportRegistry as a bean in order to support ImportAware @Configuration classes
            if (sbr != null) {
                if (!sbr.containsSingleton(IMPORT_REGISTRY_BEAN_NAME)) {
                    sbr.registerSingleton(IMPORT_REGISTRY_BEAN_NAME, parser.getImportRegistry());
                }
            }
    
            if (this.metadataReaderFactory instanceof CachingMetadataReaderFactory) {
                ((CachingMetadataReaderFactory) this.metadataReaderFactory).clearCache();
            }
        }      
    

    主要实现在processConfigBeanDefinitions这个方法中,在这个方法里,首先找到使用@Configuration注解的类,然后把这个类放入configCandidates集合中,然后调用ConfigurationClassParser类的parse方法,省略中间调用过程,最终解析是在doProcessConfigurationClass这个方法中。

        protected final SourceClass doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass)
                throws IOException {
    
            // Recursively process any member (nested) classes first
            processMemberClasses(configClass, sourceClass);
    
            // Process any @PropertySource annotations
            for (AnnotationAttributes propertySource : AnnotationConfigUtils.attributesForRepeatable(
                    sourceClass.getMetadata(), PropertySources.class,
                    org.springframework.context.annotation.PropertySource.class)) {
                if (this.environment instanceof ConfigurableEnvironment) {
                    processPropertySource(propertySource);
                }
                else {
                    logger.warn("Ignoring @PropertySource annotation on [" + sourceClass.getMetadata().getClassName() +
                            "]. Reason: Environment must implement ConfigurableEnvironment");
                }
            }
    
            // Process any @ComponentScan annotations
            Set<AnnotationAttributes> componentScans = AnnotationConfigUtils.attributesForRepeatable(
                    sourceClass.getMetadata(), ComponentScans.class, ComponentScan.class);
            if (!componentScans.isEmpty() &&
                    !this.conditionEvaluator.shouldSkip(sourceClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN)) {
                for (AnnotationAttributes componentScan : componentScans) {
                    // The config class is annotated with @ComponentScan -> perform the scan immediately
                    Set<BeanDefinitionHolder> scannedBeanDefinitions =
                            this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());
                    // Check the set of scanned definitions for any further config classes and parse recursively if needed
                    for (BeanDefinitionHolder holder : scannedBeanDefinitions) {
                        if (ConfigurationClassUtils.checkConfigurationClassCandidate(
                                holder.getBeanDefinition(), this.metadataReaderFactory)) {
                            parse(holder.getBeanDefinition().getBeanClassName(), holder.getBeanName());
                        }
                    }
                }
            }
    
            // Process any @Import annotations
            processImports(configClass, sourceClass, getImports(sourceClass), true);
    
            // Process any @ImportResource annotations
            if (sourceClass.getMetadata().isAnnotated(ImportResource.class.getName())) {
                AnnotationAttributes importResource =
                        AnnotationConfigUtils.attributesFor(sourceClass.getMetadata(), ImportResource.class);
                String[] resources = importResource.getStringArray("locations");
                Class<? extends BeanDefinitionReader> readerClass = importResource.getClass("reader");
                for (String resource : resources) {
                    String resolvedResource = this.environment.resolveRequiredPlaceholders(resource);
                    configClass.addImportedResource(resolvedResource, readerClass);
                }
            }
    
            // Process individual @Bean methods
            Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass);
            for (MethodMetadata methodMetadata : beanMethods) {
                configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
            }
    
            // Process default methods on interfaces
            processInterfaces(configClass, sourceClass);
    
            // Process superclass, if any
            if (sourceClass.getMetadata().hasSuperClass()) {
                String superclass = sourceClass.getMetadata().getSuperClassName();
                if (!superclass.startsWith("java") && !this.knownSuperclasses.containsKey(superclass)) {
                    this.knownSuperclasses.put(superclass, configClass);
                    // Superclass found, return its annotation metadata and recurse
                    return sourceClass.getSuperClass();
                }
            }
    
            // No superclass -> processing is complete
            return null;
        }
    

    这个方法里主要是处理类上的@PropertySource、@ComponentScan、 @Import、@ImportResource、@Bean注解,这里主要讲@ComponentScan这个注解,就是下面这段代码。

            // Process any @ComponentScan annotations
            Set<AnnotationAttributes> componentScans = AnnotationConfigUtils.attributesForRepeatable(
                    sourceClass.getMetadata(), ComponentScans.class, ComponentScan.class);
            if (!componentScans.isEmpty() &&
                    !this.conditionEvaluator.shouldSkip(sourceClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN)) {
                for (AnnotationAttributes componentScan : componentScans) {
                    // The config class is annotated with @ComponentScan -> perform the scan immediately
                    Set<BeanDefinitionHolder> scannedBeanDefinitions =
                            this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());
                    // Check the set of scanned definitions for any further config classes and parse recursively if needed
                    for (BeanDefinitionHolder holder : scannedBeanDefinitions) {
                        if (ConfigurationClassUtils.checkConfigurationClassCandidate(
                                holder.getBeanDefinition(), this.metadataReaderFactory)) {
                            parse(holder.getBeanDefinition().getBeanClassName(), holder.getBeanName());
                        }
                    }
                }
            }
    

    这里主要看this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName())这句,看下这个parse方法的实现。

        public Set<BeanDefinitionHolder> parse(AnnotationAttributes componentScan, final String declaringClass) {
    ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(this.registry,
                    componentScan.getBoolean("useDefaultFilters"), this.environment, this.resourceLoader);
            。。。。
            return scanner.doScan(StringUtils.toStringArray(basePackages));
        }
    

    这个方法前面都是解析@ComponentScan注解的属性,最后调用doScan这个方法。

        protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
            Assert.notEmpty(basePackages, "At least one base package must be specified");
            Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<BeanDefinitionHolder>();
            for (String basePackage : basePackages) {
                Set<BeanDefinition> candidates = findCandidateComponents(basePackage);
                for (BeanDefinition candidate : candidates) {
                    ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);
                    candidate.setScope(scopeMetadata.getScopeName());
                    String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);
                    if (candidate instanceof AbstractBeanDefinition) {
                        postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);
                    }
                    if (candidate instanceof AnnotatedBeanDefinition) {
                        AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
                    }
                    if (checkCandidate(beanName, candidate)) {
                        BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
                        definitionHolder =
                                AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
                        beanDefinitions.add(definitionHolder);
                        registerBeanDefinition(definitionHolder, this.registry);
                    }
                }
            }
            return beanDefinitions;
        }
    

    basePackages指的就是使用@ComponentScan注解的类所在的包,然后利用findCandidateComponents获取此包下的使用@Component注解的类路径,然后遍历这些类。
    在这个遍历循环中,主要做下面内容:
    (1)调用AnnotationScopeMetadataResolver的resolveScopeMetadata方法,获取此类中的@Scope注解的属性,封装为ScopeMetadata对象返回.(2) 生成beanName。
    (3)处理这个类上的常用注解,例如@Lazy、@Primary等。
    (4)根据之前解析的@Scope注解,调用AnnotationConfigUtils.applyScopedProxyMode方法确定是否生成一个代理对象。
    (5)将代理生成的BeanDefinitionHolder对象放入beanDefinitions这个集合中。
    (6)将生成的BeanDefinitionHolder对象注册到DefaultListableBeanFactory类中beanDefinitionMap中。
    这个循环完成,这个项目中自定义的bean都添加到了DefaultListableBeanFactory类中beanDefinitionMap中了。

    相关文章

      网友评论

          本文标题:springboot源码4--bean加载

          本文链接:https://www.haomeiwen.com/subject/ykvqqqtx.html