Spring源码首先要说一下beanDefinition, beanDefinition是生成bean时候的规则,包括
beanClass,是否是单例多例,primay,懒加载等一系列信息.
分析源码,springboot启动项目中run方法,会初始化注解上下文,构造函数里有成员变量
this.reader = new AnnotatedBeanDefinitionReader(this),在初始化
AnnotatedBeanDefinitionReader的时候,会将最重要的类ConfigurationClassPostProcessor类put进AbstractApplicationContext的成员变量beanFactoryPostProcessors中,
ConfigurationClassPostProcessor是
BeanDefinitionRegistryPostProcessor(bean定义的后置注册器)和
BeanFactoryPostProcessor(bean定义的后置处理器)
Run方法还会执行spring最重要的方法 refresh
其中refresh有两个方法
invokeBeanFactoryPostProcessors(beanFactory);对于每个bean生成对应的
beanDefintion,put进beanDefinitionMaps中
finishBeanFactoryInitialization(beanFactory);遍历所有的beanDefinition,初始化bean,会执行bean的后置处理器和各种aware
先分析一下invokeBeanFactoryPostProcessors(beanFactory);方法
首先遍历AbstractApplicationContext的beanFactoryPostProcessors成员变量中
BeanFactoryPostProcessor的子类,默认是ConfigurationClassPostProcessor
- 首先执行ConfigurationClassPostProcessor的postProcessBeanDefinitionRegistry(bean定义的后置注册器)方法,具体首先遍历beanDefinitionMap,此时的beanDefinitionMap包含了springboot启动类,其余的是springboot自带的, 判断是否标注了@Configuration@Component@ComponentScan@Import@ImportResource注解,
添加configCandidates(候选配置)里,configCandidates一般只有springboot的启动类,就是标注了@SpringBootApplication的类,复合注解其中就包含了@ComfigurationScan,继续遍历configCandidates
调用pase方法,主要通过@ComfigurationScan扫描包,扫描包下所有的类,再遍历判断是否@Component注解,并存放到ConfigurationClass中,如果被扫描的类依然标注了
@ComfigurationScan注解,递归的扫描,直到没有标注@ComfigurationScan,
继续判断是否@Import注解,通过返回的全类名数组,继续判断是否@ComfigurationScan,重复上面的过程,最终把所有的符合条件的类封装为ConfigurationClass,并put进
configurationClasses,此时上面的过程,在put进configurationClasses的同时,被扫描的类标注了@Component注解也会put进beanDefinitionMap中,这些类也存在于configurationClasses中,遍历configurationClasses,判断是类中的方法否标注了@Bean 是否是通过@Import导入的,将符合的类封装beanDefinition put进BeanDefinitonMap中 - ConfigurationClassPostProcessor的postProcessBeanFactory方法,遍历
beanDefinitonMap,判断类是否是完全配置类,也就是标注了@Configuraion注解的类
将beanDefinition的beanClass替代为 用Cglib代理之后的类.
网友评论