spring源码解析之ioc-invokeBeanFactoryPostProcessors

接下来本应该是postProcessBeanFactory(beanFactory);
但是他是留给子类去做处理的,我们这里没用他的具体业务,所以直接略过

我们继续往下走

invokeBeanFactoryPostProcessors(beanFactory);

执行beanFactoryPostProcessor

protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
		//首先获取beanFactoryPostProcessor  再去执行  往下看怎么执行的
		PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());

		......
	}
//我们获取到的beanFactoryPostProcessor为null  也就是i第二个参数是null
public static void invokeBeanFactoryPostProcessors(
			ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {

		// Invoke BeanDefinitionRegistryPostProcessors first, if any.
		Set<String> processedBeans = new HashSet<>();

		//我们的beanFactory就是属于BeanDefinitionRegistry
		if (beanFactory instanceof BeanDefinitionRegistry) {
			BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
			List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
			List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();

			//上面也说了  beanFactoryPostProcessors为null   直接过
			for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
				if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
					BeanDefinitionRegistryPostProcessor registryProcessor =
							(BeanDefinitionRegistryPostProcessor) postProcessor;
					//执行以下postXxx方法
					registryProcessor.postProcessBeanDefinitionRegistry(registry);
					registryProcessors.add(registryProcessor);
				}
				else {
					regularPostProcessors.add(postProcessor);
				}
			}

			
			List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();

			//根据类型获取bean   BeanDefinitionRegistryPostProcessor类型
			String[] postProcessorNames =
					beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
			for (String ppName : postProcessorNames) {
			//设置了优先级,则先加载这个bean  注意!这里是加载bean
				if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
					currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
					processedBeans.add(ppName);
				}
			}
			//将上面已经注册好的bean进行排序  注意bean的类型BeanDefinitionRegistryPostProcessor
			sortPostProcessors(currentRegistryProcessors, beanFactory);
			registryProcessors.addAll(currentRegistryProcessors);
			//执行以下postXxx方法
			invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
			currentRegistryProcessors.clear();

			// 同上
			postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
			for (String ppName : postProcessorNames) {
				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();

			// 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)) {
						currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
						processedBeans.add(ppName);
						reiterate = true;
					}
				}
				sortPostProcessors(currentRegistryProcessors, beanFactory);
				registryProcessors.addAll(currentRegistryProcessors);
				invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
				currentRegistryProcessors.clear();
			}

			// Now, invoke the postProcessBeanFactory callback of all processors handled so far.
			invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
			invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);

			总结以下
			上面代码主要是获取BeanDefinitionRegistryPostProcessor类型的bean名字
			然后根据是
			否实现了PriorityOrdered接口---》实例化这部分bean  排序  执行postProcessBeanDefinitionRegistry方法
			是否实现了Ordered接口---》实例化这部分bean  排序  执行postProcessBeanDefinitionRegistry方法
			没有实现上面的接口,最后实例化 排序 执行postProcessBeanDefinitionRegistry
			
			最后,在执行postProcessBeanFactory方法
			
			因为这部分bean首先是BeanDefinitionRegistryPostProcessor接口的实现
			其次是BeanFactoryPostProcessor接口的实现
			所以他将实现的两个接口的方法都去执行了
			
			就解释这么多  也就是按照优先级去加载了bean  然后运行接口定义的方法
		}

		else {
			// Invoke factory processors registered with the context instance.
			invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
		}

		//获取beanFactoryPostProcessor类型的bean
		String[] postProcessorNames =
				beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);

		// Separate between BeanFactoryPostProcessors that implement PriorityOrdered,
		// Ordered, and the rest.
		List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
		List<String> orderedPostProcessorNames = new ArrayList<>();
		List<String> nonOrderedPostProcessorNames = new ArrayList<>();
		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);
			}
		}

		//排序  执行postProcessBeanFactory方法   我们自己的beanFactory会在这一块去执行
		sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
		invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);

		// Next, invoke the BeanFactoryPostProcessors that implement Ordered.
		List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());
		for (String postProcessorName : orderedPostProcessorNames) {
			orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
		}
		sortPostProcessors(orderedPostProcessors, beanFactory);
		invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);

		// Finally, invoke all other BeanFactoryPostProcessors.
		List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());
		for (String postProcessorName : nonOrderedPostProcessorNames) {
			nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
		}
		invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);


		简单说一下:这一块跟上面解释一样,根据优先级去加载bean,然后去执行对应的方法

		beanFactory.clearMetadataCache();
	}

到了这里是不是就结束了?

通过下图我们可以发现,在执行下行代码之前,我们的map只有6个定义的bean

PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, this.getBeanFactoryPostProcessors());

在这里插入图片描述
再看看执行完之后有多少bean
在这里插入图片描述
这里可以很清楚的看到map的size变为了14 这说明在这个里面注册了我们注解标注的相关的bean

我们再来仔细分析下哪里注册了bean
在上面的代码分析中,我们知道了他会根据优先级顺序去加载BeanDefinitionRegistryPostProcessor类型的bean,而从这个类的名字我们可以猜的出来,他就是用来负责注册beanDefinition的。所以,肯定是在加载完这个bean之后,执行他的postProcessBeanDefinitionRegistry方法来去注册bean

(其实是ConfigurationClassPostProcess,他来进行注解方式的bean的加载)

所以我们就来看看他的postProcessBeanDefinitionRegistry方法!

执行beanDefinition的注册

PostProcessorRegistrationDelegate  244 line

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

        while(var2.hasNext()) {
            BeanDefinitionRegistryPostProcessor postProcessor = (BeanDefinitionRegistryPostProcessor)var2.next();
            //beanDefinition的注册  往下看
            postProcessor.postProcessBeanDefinitionRegistry(registry);
        }

    }
 public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
 		//beanFactory的id  判断这个beanFactory是否已处理。
        int registryId = System.identityHashCode(registry);
        if (this.registriesPostProcessed.contains(registryId)) {
            throw new IllegalStateException("postProcessBeanDefinitionRegistry already called on this post-processor against " + registry);
        } else if (this.factoriesPostProcessed.contains(registryId)) {
            throw new IllegalStateException("postProcessBeanFactory already called on this post-processor against " + registry);
        } else {
            this.registriesPostProcessed.add(registryId);
            //没处理过,来进行处理
            this.processConfigBeanDefinitions(registry);
        }
    }

注解类型的beanDefinition的加载

ConfigurationClassPostProcessor  155 line

public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
        List<BeanDefinitionHolder> configCandidates = new ArrayList();
        //获取已注册的bd
        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 (beanDef.getAttribute(ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTE) != null) {
                if (this.logger.isDebugEnabled()) {
                    this.logger.debug("Bean definition has already been processed as a configuration class: " + beanDef);
                }
               //我们的bean的metadata(元数据)里面会有一个key为org.springframework.context.annotation.Configuration的属性(AnnotationAttributes)
               //这个是在注册我们的配置类的时候去设置的 在下面if里面判断
               //判断这个属性不为null,直接返回true  不太懂得可以看if里面得逻辑  不是重点 略过
               //abd.getMetadata().getAnnotationAttributes("org.springframework.context.annotation.Configuration")
               
            } else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) {
                configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));
            }
        }
		
		//配置类不为空
        if (!configCandidates.isEmpty()) {
            //排序相关的省略
			
			......
			
			//配置类的解析器  就是用这个去解析配置类
            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());

			//循环去注册每一个配置需要注入的bean
            do {
            	//1、解析配置类
                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也当成一个配置类,再去解析这个配置类!!!(非方法注入的bean)
				//这一块的解析主要是以下几种
				//1、解析注册@Import导入的类的信息
				//2、解析方法注入的bean  也就是在配置类中使用@Bean注入
				//3、解析注册@ImportResource注解导入的xml文件
				//4、aop相关 略过 以后在分析
                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;
					
					//遍历已经注册好的bean
                    for(int var14 = 0; var14 < var24; ++var14) {
                        String candidateName = var23[var14];
                        //oldCandidateNames存放的是配置类的名字 
                        //如果有bean不在配置类里面  去校验(校验方式看上面的解释)这个类是不是配置类,是的话加入配置类集合
                        //在下一次循环时,去处理这个配置类
                        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());

			//其他处理  略过
            ......
        }
    }

接着看重点 解析配置类!!!

ConfigurationClassPaeser  109 line

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

        this.deferredImportSelectorHandler.process();
    }
ConfigurationClassParser   162 line

protected void processConfigurationClass(ConfigurationClass configClass, Predicate<String> filter) 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, filter);

            do {
            	//解析配置类
                sourceClass = this.doProcessConfigurationClass(configClass, sourceClass, filter);
            } while(sourceClass != null);
			//保存已经处理过的配置类
            this.configurationClasses.put(configClass, configClass);
        }
    }

解析配置类 这一块是一个核心内容

ConfigurationClassParser  189 line

protected final ConfigurationClassParser.SourceClass doProcessConfigurationClass(ConfigurationClass configClass, ConfigurationClassParser.SourceClass sourceClass, Predicate<String> filter) throws IOException {

		//注意!!! 主要有@Component注解,就是配置类!!!而不是必须是@Configuration才可以
		
        if (configClass.getMetadata().isAnnotated(Component.class.getName())) {
        	//处理内部类 (校验内部类是不是配置类,是的话优先处理内部类 跟我们外部配置类同样的逻辑) 这一块没有 略过
            this.processMemberClasses(configClass, sourceClass, filter);
        }

		//处理@PropertySource   @PropertySources注解  这一块我没标注  略过把 其实都大同小异
        Iterator var4 = AnnotationConfigUtils.attributesForRepeatable(sourceClass.getMetadata(), PropertySources.class, PropertySource.class).iterator();

        AnnotationAttributes importResource;
        while(var4.hasNext()) {
            importResource = (AnnotationAttributes)var4.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");
            }
        }

		//我们的重点  处理@componentScans @ComponentScan注解
		//这一块拿到的信息(排除规则、扫描的包路径等等)在下图 可以参考
        Set<AnnotationAttributes> componentScans = AnnotationConfigUtils.attributesForRepeatable(sourceClass.getMetadata(), ComponentScans.class, ComponentScan.class);
        //再次判断是否需要跳过
        if (!componentScans.isEmpty() && !this.conditionEvaluator.shouldSkip(sourceClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN)) {
            Iterator var14 = componentScans.iterator();

            while(var14.hasNext()) {
                AnnotationAttributes componentScan = (AnnotationAttributes)var14.next();
                Set<BeanDefinitionHolder> scannedBeanDefinitions = this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());
                Iterator var8 = scannedBeanDefinitions.iterator();

                while(var8.hasNext()) {
                	//解析完之后,拿到返回的bd
                    BeanDefinitionHolder holder = (BeanDefinitionHolder)var8.next();
                    BeanDefinition bdCand = holder.getBeanDefinition().getOriginatingBeanDefinition();
                    if (bdCand == null) {
                        bdCand = holder.getBeanDefinition();
                    }
					
					//判断本次注册的bd是不是配置类,是的话,继续以配置类的方式去处理
					//(跟我们第一个配置类解析之前的判断是一样的)
                    if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) {
                        this.parse(bdCand.getBeanClassName(), holder.getBeanName());
                    }
                }
            }
        }
		
		//处理import导入的class,判断导入的类是不是配置类,是的话按照配置类方式去处理  可以略过了把
        this.processImports(configClass, sourceClass, this.getImports(sourceClass), filter, true);
        //处理@ImportResource  有的话,将文件路径保存起来 后面去解析 上面有提到哦
        importResource = AnnotationConfigUtils.attributesFor(sourceClass.getMetadata(), ImportResource.class);
        if (importResource != null) {
            String[] resources = importResource.getStringArray("locations");
            Class<? extends BeanDefinitionReader> readerClass = importResource.getClass("reader");
            String[] var20 = resources;
            int var22 = resources.length;

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

		//处理以方法形式需要注册的bean,将其包装成BeanMethod保存起来  后续处理  上面也有提到哦
        Set<MethodMetadata> beanMethods = this.retrieveBeanMethodMetadata(sourceClass);
        Iterator var18 = beanMethods.iterator();

        while(var18.hasNext()) {
            MethodMetadata methodMetadata = (MethodMetadata)var18.next();
            configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
        }
		
		//配置类如果实现了接口,也得去处理接口里面以方法形式注册的bean (包装保存,后续处理)
        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;
    }

在这里插入图片描述
总结一下上面的代码都做了什么

1、配置类有成员类,判断成员类是不是配置类,是的话,先以配置类方式处理成员类

2、如果有@PropertySources 、@PropertySource 处理 这一块具体操作我没分析

3、@ComponentScans 与@ComponentScan 注解的处理 这一块是重点

4、如果有@Import注解,判断是否实现了ImportSelector接口、ImportBeanDefinitionRegistrar接口
判没有的话,以配置类方式去处理 有的话,按照其他逻辑处理(ImportSelector其实是可以自定义导入多个类,然后判断这些类是否实现了ImportSelector、ImportBeanDefinitionRegistrar接口,没有的话,一配置类方式去处理)

5、处理@ImportResourceI导入的xml文件,将其保存起来,后续以xml方式去加载

6、处理@Bean,方法形式需要注入的bean,将其包装成BeanMethod保存,后续去处理

7、配置类实现了接口,处理接口内部以@Bean形式注入的bean 同6

接下来我们仔细看下 3 是如何去处理的

@ComponentScan 与@ComponentScans的处理方式

CompinentScanAnnotationParser  46 line

public Set<BeanDefinitionHolder> parse(AnnotationAttributes componentScan, final String declaringClass) {
		//一些设置  可略过
        ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(this.registry, componentScan.getBoolean("useDefaultFilters"), this.environment, this.resourceLoader);
        Class<? extends BeanNameGenerator> generatorClass = componentScan.getClass("nameGenerator");
        boolean useInheritedGenerator = BeanNameGenerator.class == generatorClass;
        scanner.setBeanNameGenerator(useInheritedGenerator ? this.beanNameGenerator : (BeanNameGenerator)BeanUtils.instantiateClass(generatorClass));
        ScopedProxyMode scopedProxyMode = (ScopedProxyMode)componentScan.getEnum("scopedProxy");
        if (scopedProxyMode != ScopedProxyMode.DEFAULT) {
            scanner.setScopedProxyMode(scopedProxyMode);
        } else {
            Class<? extends ScopeMetadataResolver> resolverClass = componentScan.getClass("scopeResolver");
            scanner.setScopeMetadataResolver((ScopeMetadataResolver)BeanUtils.instantiateClass(resolverClass));
        }
		//设置加载的资源后缀名
        scanner.setResourcePattern(componentScan.getString("resourcePattern"));
        AnnotationAttributes[] var15 = componentScan.getAnnotationArray("includeFilters");
        int var8 = var15.length;

		//设置需要包括资源路径
        int var9;
        AnnotationAttributes filter;
        Iterator var11;
        TypeFilter typeFilter;
        for(var9 = 0; var9 < var8; ++var9) {
            filter = var15[var9];
            var11 = this.typeFiltersFor(filter).iterator();

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

		//设置需要排除的资源路径
        var15 = componentScan.getAnnotationArray("excludeFilters");
        var8 = var15.length;

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

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

		//设置是否是要懒加载
        boolean lazyInit = componentScan.getBoolean("lazyInit");
        if (lazyInit) {
            scanner.getBeanDefinitionDefaults().setLazyInit(true);
        }

		//设置扫描的包路径
        Set<String> basePackages = new LinkedHashSet();
        String[] basePackagesArray = componentScan.getStringArray("basePackages");
        String[] var19 = basePackagesArray;
        int var21 = basePackagesArray.length;

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

		//设置需要扫描的包路径
        Class[] var20 = componentScan.getClassArray("basePackageClasses");
        var21 = var20.length;

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

		//如果没设置basePackage与basePackageClasses  将配置类所在的包作为默认的扫描路径
        if (basePackages.isEmpty()) {
            basePackages.add(ClassUtils.getPackageName(declaringClass));
        }
		
		//这个是干嘛的??????没仔细研究
        scanner.addExcludeFilter(new AbstractTypeHierarchyTraversingFilter(false, false) {
            protected boolean matchClassName(String className) {
                return declaringClass.equals(className);
            }
        });
        //解析处理  往下看
        return scanner.doScan(StringUtils.toStringArray(basePackages));
    }

解析处理

ClassPathBeanDefinitionScanner  105 line

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];
            //根据basePackage去获取资源流,然后创建ScannedGenericBeanDefinition对象,收集起来返回
            //(这里是加载的编译之后的class文件哦)   往下看是怎么去处理的
            Set<BeanDefinition> candidates = this.findCandidateComponents(basePackage);
            Iterator var8 = candidates.iterator();

            while(var8.hasNext()) {
            	//拿到加载好的beanDefinition信息
                BeanDefinition candidate = (BeanDefinition)var8.next();
                ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);
                candidate.setScope(scopeMetadata.getScopeName());
                String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);
                if (candidate instanceof AbstractBeanDefinition) {
                	//做一些处理   略过
                    this.postProcessBeanDefinition((AbstractBeanDefinition)candidate, beanName);
                }

                if (candidate instanceof AnnotatedBeanDefinition) {
					//设置dependon、懒加载呀、primary呀、描述呀role等注解的信息  跟加载配置类时是一样得
                    AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition)candidate);
                }

				//检查是否已经被注册了  ,没有的话注册到map中
                if (this.checkCandidate(beanName, candidate)) {
                    BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
                    //包装一下
                    definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
                    //保存已经加载好的beanDefinition
                    beanDefinitions.add(definitionHolder);
                    //注册到map中
                    this.registerBeanDefinition(definitionHolder, this.registry);
                }
            }
        }

        return beanDefinitions;
    }

ok 我们来看下具体是怎么读取basePackage 并且创建bd的

ClassPathScanningCandidateComponentProvider  267 line

private Set<BeanDefinition> scanCandidateComponents(String basePackage) {
        LinkedHashSet candidates = new LinkedHashSet();

        try {
        	//获取包路径  也就是classpath/package/**/*.class
        	//我这里是classpath*:com/listener/**/*.class
            String packageSearchPath = "classpath*:" + this.resolveBasePackage(basePackage) + '/' + this.resourcePattern;
            //获取资源流
            Resource[] resources = this.getResourcePatternResolver().getResources(packageSearchPath);
            Resource[] var7 = resources;
            int var8 = resources.length;

            for(int var9 = 0; var9 < var8; ++var9) {
            	//遍历 获取每一个文件资源
                Resource resource = var7[var9];
                if (resource.isReadable()) {
                    try {
                    	//获取资源属性 封装起来
                        MetadataReader metadataReader = this.getMetadataReaderFactory().getMetadataReader(resource);
                        //这个资源是否需要排除
                        if (this.isCandidateComponent(metadataReader)) {
                            //创建bd
                            ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader);
                            //设置相关属性
                            sbd.setSource(resource);
                            //这个需要加载的类不是抽象的,也不是接口    或者 是抽象的 但是有@Lookup注解
                            if (this.isCandidateComponent((AnnotatedBeanDefinition)sbd)) {
                                //收集起来  然后返回
                                candidates.add(sbd);
                            } 
                            ......
                }
            }

            return candidates;
        } catch (IOException var14) {
            throw new BeanDefinitionStoreException("I/O failure during classpath scanning", var14);
        }
    }

到了这里 ,ComponentScan已经处理完 ,我们在看看我们走到了哪里

这里我就只贴出部分代码了
ConfigurationClassParser  189 line
......
Set<AnnotationAttributes> componentScans = AnnotationConfigUtils.attributesForRepeatable(sourceClass.getMetadata(), ComponentScans.class, ComponentScan.class);
        if (!componentScans.isEmpty() && !this.conditionEvaluator.shouldSkip(sourceClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN)) {
            Iterator var14 = componentScans.iterator();

            while(var14.hasNext()) {
                AnnotationAttributes componentScan = (AnnotationAttributes)var14.next();
                Set<BeanDefinitionHolder> scannedBeanDefinitions = this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());
                Iterator var8 = scannedBeanDefinitions.iterator();

                while(var8.hasNext()) {
                    BeanDefinitionHolder holder = (BeanDefinitionHolder)var8.next();
                    BeanDefinition bdCand = holder.getBeanDefinition().getOriginatingBeanDefinition();
                    if (bdCand == null) {
                        bdCand = holder.getBeanDefinition();
                    }

                    if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) {
                    	//进行这个parse
                        this.parse(bdCand.getBeanClassName(), holder.getBeanName());
                    }
                }
            }
        }

在解析完之后,会将我们根据@ComponentScan解析出来的所有的bean当成配置类,再去进行同样的配置类的操作
所以,我们只需要看配置类在解析完所有的之后会做什么事情

ConfigurationClassParser  162 line

do {
		//我们上面大篇幅的都是分析这个方法,他是怎么去解析配置类的
        sourceClass = this.doProcessConfigurationClass(configClass, sourceClass, filter);
    } while(sourceClass != null);
	
	//配置类解析完之后,会将其加入到一个Map中,这个是重点
	//因为后面会拿这个map,然后去处理@Import,@Bean等前面保存起来还未注册的bean的信息
    this.configurationClasses.put(configClass, configClass);

再看看我们走到了哪里 不知道下面代码在哪里的,建议仔细看下我上面的分析

//解析配置类
parser.parse(candidates);
//校验
parser.validate();
//加载配置类
this.reader.loadBeanDefinitions(configClasses);

解析上面保存起来还未处理的工作(@Import,@Bean等方式需要加载的bean)

ConfigurationClassBeanDefinitionReader  78 line

private void loadBeanDefinitionsForConfigurationClass(ConfigurationClass configClass, ConfigurationClassBeanDefinitionReader.TrackedConditionEvaluator trackedConditionEvaluator) {
        //判断是否需要跳过
        if (trackedConditionEvaluator.shouldSkip(configClass)) {
            String beanName = configClass.getBeanName();
            if (StringUtils.hasLength(beanName) && this.registry.containsBeanDefinition(beanName)) {
                this.registry.removeBeanDefinition(beanName);
            }

            this.importRegistry.removeImportingClass(configClass.getMetadata().getClassName());
        } else {
        	//该bean是以@Import导入进来的  在这里注册
            if (configClass.isImported()) {
                this.registerBeanDefinitionForImportedConfigurationClass(configClass);
            }
			
			//处理@Bean方式需要加载的bean
            Iterator var3 = configClass.getBeanMethods().iterator();
            while(var3.hasNext()) {
                BeanMethod beanMethod = (BeanMethod)var3.next();
                this.loadBeanDefinitionsForBeanMethod(beanMethod);
            }

			//处理导入的xml文件,以xml方式加载,然后注册  参考xml文件的读取方式
            this.loadBeanDefinitionsFromImportedResources(configClass.getImportedResources());
			
			//aop相关的beanDefinition的注入  请移步aop相关源码解读
            this.loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars());
        }
    }

这里我们的BeadDefinition都已经全部加载到了BeanFactory中了

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值