springboot源码之(bean的递归注册)

在prepareContext中,用loader调用load方法,loader是 BeanDefinitionLoader,在BeanDefinitionLoader的构造方法中,
会实例化一个AnnotatedBeanDefinitionReader,在reader的构造方法中,
有一个静态方法registerAnnotationConfigProcessors,里面注册一个ConfigurationClassPostProcessor,
实现了BeanDefinitionRegistryPostProcessor进而实现了BeanFactoryPostProcessor。
而applicationContext在refresh的时候,调用invokeBeanFactoryPostProcessors(beanFactory);
在该方法里,调用了PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors这个静态方法,
这里面取出所有的BeanFactoryPostProcessor和BeanDefinitionRegistryPostProcessor,并调用两个接口的方法,但是最终都是调用
processConfigBeanDefinitions方法,先取出当前工厂中的beanDefinitions(一般除了系统自己的一些indicator,就是run方法中传入的object数组的内容,一般就是一个启动类),
并不是所有的这些初始的beanDefinitions都会被解析
判断的逻辑是:
1、是否有@Import,@Component,@ImportSource,@ComponentScan之一
2、再判断里面是否有@Bean方法。
这个逻辑也很好理解,因为如果这五个注解都没有,那么基本上也就不是一个想引入其他bean的configuration类。
进入候选之后,PostProcessor生成parser,解析候选,而接下来所有的五个注解解析出来的beanDefinition,包括从内部类,和父类中一共七个通道,
不用再判断是否含有这五个注解,这是因为解析的逻辑也是寻找这五个注解,无非就是麻烦一点。
@Import的解析逻辑,对于被import进来的每一个类:
分四种情况:
1、实现了ImportSelector接口的,且 实现了其子接口 DeferredImportSelector的,先放进一个list,在parse方法执行完之后,遍历list,取出其中的selector,调用
import方法, 返回String[]数组,遍历数组,调用processImports方法重新解析import(再走一遍1234)
2、实现了ImportSelector接口的,但没有实现其子接口 DeferredImportSelector的,直接调用import方法,递归调用processImports方法(也就是再走一遍1234)
3、实现了ImportBeanDefinitionRegistrar接口的,添加到一个list中,在后来的reader的loadBeanDefinitions中调用registerBeanDefinitions方法向工厂中注册bean
4、如果以上都不是,当做配置类解析上面的五个注解。
@ComponentScan注解的解析比较简单,看看包里面所有的类,根据filter(默认的有两个过滤器,过滤@component@Named等三个注解),
如果为空,默认是类当前所在的文件夹(ClassUtils.getPackageName)。加载,解析五个注解。
@PropertySource是解析配置文件
@ImportResource是导入xml文件?
@Bean是生成一个factoryBeanMethod,实例化的时候反射调用@Bean的方法

猜你喜欢

转载自www.cnblogs.com/chuliang/p/9816072.html