述
上文中,了解了配置类解析的一个入口和整体的流程,本文来详细的了解一下配置类解析的逻辑,也就是上文说的 ConfigurationClassPostProcessor.processConfigBeanDefinitions()
这个方法中 do-while 循环的 do 部分,看一下他具体是如何处理的
源码跟踪
重点是这里的 parse()
方法,进入看一下具体处理逻辑
ConfigurationClassParser$parse
这里做个类型判断,通常情况都是 AnnotatedBeanDefinition
类型的, 进入下面的 parse()
方法看一下
这里 3 个重载方法都一样,都是 new 了一个 ConfigurationClass
对象,然后调用了 processConfigurationClass()
这个方法, 然后以 AnnotatedBeanDefinition
类型为例,看看 ConfigurationClass
对象中都有哪些属性
ConfigurationClassParser$processConfigurationClass
然后看一下 processConfigurationClass
这个方法
这里有个比较重要的集合是 configurationClasses
,是一个 Map 集合, processConfigurationClass()
方法处理完毕后,会把当前类放进去
这个方法里面先调用了一个 asSourceClass()
这个方法,然后是一个 do-while 循环,里面又调用了 doProcessConfigurationClass()
方法
ConfigurationClassParser$asSourceClass
先来看一下这个 asSourceClass()
方法,如下
最终是返回了一个 SourceClass
对象, 构造方法如下
ConfigurationClassParser$doProcessConfigurationClass
返回来再来看一下 doProcessConfigurationClass()
这个方法,如下
这里会一次判断是否有这些注解,然后依次处理,具体处理逻辑我们之后再说, 最终会进入一个if判断,如果有父类就返回父类,没有的话,返回 null ,具体的判断逻辑如下:
如果有父类,并且符合其他条件,就返回出去,供外面的 do-while 继续循环
最终结束后,parse方法就处理完成了,之后会进入下面的 parser.validate()
方法
ConfigurationClassParser$validate
点进去看一下,具体是如何做的验证
继续往下
验证完成之后,回到 do 方法体内, 会声明一个 configClasses
集合,然后值是 parse
方法解析出来的所有配置类,然后移除掉处理过的,再获得一个 ConfigurationClassBeanDefinitionReader
对象,调用其 loadBeanDefinitions()
方法
ConfigurationClassBeanDefinitionReader$loadBeanDefinitions
这个方法的主要作用就是,加载所有的 BeanMethod , 然后将返回值注册到容器中, 这就是为什么我们用 @Bean
注解修饰的方法返回的对象会注册到 Spring 容器中
处理完成之后添加到一个处理过 alreadyParsed
的集合中,然后把 candidates
结合清空
之后是一个判断详细的看一下这个判断的具体作用
这个判断的作用就是处理 @Bean
注入的新的 BeanDefinition
,之后继续 do-while 循环,直到没有新的 BeanDefinition
以上就是这个 do-while 循环中做的全部事情, 其实重点的处理逻辑都在 ConfigurationClassParser$doProcessConfigurationClass
这个方法中, 下文中会详细分析
总结
最后把这个 do-while 中的逻辑做一个总结
配置类的解析入口是在 ConfigurationClassPostProcessor$processConfigBeanDefinitions()
这个方法的 do-while 循环体当中, 循环终止的条件是配置类没有向 BeanFactory 中注册新的 BeanDefinition
然后整个 do-while 循环的流程图如下:
然后 parse()
方法的逻辑:
最后 doProcessConfigurationClass()
方法中的处理逻辑