接下来本应该是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中了