Spring---invokeBeanFactoryPostProcessors(beanFactory)方法流程
2022-07-15 16:29:14 0 举报
Spring源码
作者其他创作
大纲/内容
1、String[] candidateNames = registry.getBeanDefinitionNames();2、for (String beanName : candidateNames) { ... }
最后会注册到beanDefinitionMap中
isCandidateComponent(sbd)
this.importBeanDefinitionRegistrars.put()
scanner.doScan(XXX)
postProcessBeanDefinition()
processImports()
getBeanFactoryPostProcessors()返回的是null,这个需要我们在外面手动设置才会有值。
在这个方法里会解析加了@Configuration的配置类,解析@ComponentScan的扫描包,以及@Import等注解
接着开始解析@Import注解了
this.deferredImportSelectors.add(holder)
一直点击这个方法进入会发现,这个方法后面又会调用processImports()这个方法, 然后,processImports()方法又主动调用processConfigurationClass()方法,这是一个递归调用。 为什么要这么设计呢?因为Import进来的普通类,也有可能被加了@Import注解,或@ComponentScan注解,或者其他注解,所以普通类需要再次被解析
processConfigurationClass(XXX)
开始解析@Component注解里的属性:nameGenerator、scopedProxy、scopeResolver、resourcePattern、includeFilters、excludeFilters、lazyInit、basePackages等等,然后把解析出的值保存到scanner对象里
false
AnnotationConfigUtils.processCommonDefinitionAnnotations()
用来解析@Component、@Service、@Respository注解
configClass.addImportBeanDefinitionRegistrar()
candidate.isAssignable(ImportBeanDefinitionRegistrar.class)
currentRegistryProcessors.add(beanFactory.getBean()
循环处理没一个resource
检查给定候选的 bean 名称,确定相应的 bean 定义是否需要注册或与现有定义冲突。
处理@PropertySource注解,@PropertySource注解用来加载properties文件
this.includeFilters
ConfigurationClassUtils.checkConfigurationClassCandidate()
ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(XXX)
// 开始解析parser.parse(candidates)
判断是否有@Component注解。 @Configuration注解嵌套了@Component注解,因此进入if分支进行处理。然后会递归处理我们配置类里的内部类,一般不会写内部类
candidates.add(sbd)
candidate instanceof AbstractBeanDefinition
把传进来的类似命名空间形式的字符串转换成类似类文件地址的形式,然后在前面加上classpath*:// 即:com.xx=>classpath*:com/xx/**/*.class
在这里会进一步开始解析注解:@Lazy、@Primary、@DependsOn、@Role、@Description,// 如果类上有这些注解,将把注解上设置的属性值设置到candidate对象上
判断是否符合候选组的要求
这里也只是把添加到set集合里,并未解析成beanDefinition
true
解析配置类里@Bean方法
selector instanceof DeferredImportSelector
ConfigurationClassParser#processConfigurationClass()
获取包下所有文件
retrieveBeanMethodMetadata(sourceClass)
scanCandidateComponents(String basePackage)
ConfigurationClassPostProcessor#processConfigBeanDefinitions()
解析判断@Conditional
没有实现DeferredImportSelector,是普通的ImportSelecor,递归调用
#invokeBeanFactoryPostProcessors(beanFactory)
candidate.isAssignable(ImportSelector.class)
isCandidateComponent(metadataReader)
String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX +resolveBasePackage(basePackage) + '/' + this.resourcePattern;Resource[] resources = getResourcePatternResolver().getResources(packageSearchPath);
解析@ImportResource注解
Spring有个@Conditional的注解,在这个注解里,我们可以创建一个实现Condition接口的过滤类,我们可以重新过滤条件。这里会先判断我们的注解是不是@Conditional,如果是,进一步判断是否满足过滤条件
AbstractApplicationContext#refresh()
ParserStrategyUtils.instantiateClass()
config != null || isConfigurationCandidate(metadata)
解析@componentScan
config != null && !Boolean.FALSE.equals(config.get(\"proxyBeanMethods\"))
candidate instanceof AnnotatedBeanDefinition
processPropertySource(propertySource)
解析@Conditional
获得所有的BeanDefinition的Name,放入candidateNames数组,接着循环获取beanName所对应的beanDefinition,并且判断beanDefinition是否为配置类,这里配置类会有两种,FULL和LITE,如果是的话,则会在beanDefinition的属性上CONFIGURATION_CLASS_ATTRIBUTE设置相对于的属性值。
将一些默认值设置给检测出来的ben
parse()
doScan(String... basePackages)
递归解析配置类
isAnnotated(Component.class.getName())
这个方法里会使用适当的构造函数对类进行实例化,如果candidateClass类实现了{@link BeanClassLoaderAware}、// {@link BeanFactoryAware}、{@link EnvironmentAware} 和 {@link ResourceLoaderAware},// 这个方法里会调用实现接口的方法,就是各种aware()方法
Set<BeanDefinition> candidates = findCandidateComponents(basePackage)
// 创建配置类解析器ConfigurationClassParser parser = new ConfigurationClassParser()
普通的类
加载已注册的bean的postProcessor,也就是在this.reader = new AnnotatedBeanDefinitionReader(this)我们注册了Srping内置的各种配置类。从里面找到实现BeanDefinitionRegistryPostProcessor接口的类,也就是:ConfigurationClassPostProcessor
this.componentScanParser.parse()
ConfigurationClassPostProcessor#postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry)
this.excludeFilters
0 条评论
下一页