扫描生成beandefinition并实例化单例bean
2025-04-01 13:19:23 1 举报
在Spring框架中,扫描生成BeanDefinition并实例化单例bean的源码流程
作者其他创作
大纲/内容
获取TypeFilter对应的注解类型全名
遍历得到的Set<BeanDefinition>
是
否
在这里创建对象的时候beanClass设置的是classname而不是class对象。因为这里使用的是ASM技术来解析class文件,还没有加载class对象,因此只能设置classname
实现了接口
验证通过后beandefinition(也就是前面ScannedGenericBeanDefinition)添加到BeanDefinition集合中
获取单例bean,并判断该bean是否实现SmartInitializingSingleton接口
创建单例bean(getBean(beanName))
找到可能的BeandefinitionfindCandidateComponents
再次遍历beanNames
根据注解类型名和指定的扫描路径从index中去匹配到注解对应的candidate的类型全名的set集合存放到总的types中
getBean(\"&\" + beanName)获取的是FactoryBean的单例beangetBean(beanName)获取的是getObject返回的bean注意:从getObject返回的bean,它没有经过bean的完整的生命周期,它的生命周期是从初始化后开始的(为的是aop)
找到则直接返回
重新生成一个rootbeandefinition(new RootBeanDefinition(bd))
在getBean方法中会调用getObject方法来创建bean,该bean会存入factoryBeanObjectCache缓存中
(顶层类或是静态内部类 && (具体类(即非接口或抽象类) || (抽象类 && 有lookup注解的方法)))
当前beanDefiniton是否有父beanDefinition(bd.getParentName())
方法结束
没有spring.components
这个节点已经是所有非懒加载单例bean都创建完毕的时候了
根据beanname从mergedBeanDefinitions找rootBeanDefiniton
合并beandefiniton的目的是为了让子bean去继承父bean的一些属性(子bean没有的)。核心逻辑是:通过子bean去获取父bean,然后再clone一份父bean生成rootbeandifiniton,最后再用原有的子bean去覆盖一下rootbeandifiniton的属性,这样就能保证子bean拥有的属性不变,而只是扩展了一些属性而已。注意:原来的父子bean不动,是去生成一个新的beandefiniton
创建FactoryBean的单例bean(getBean(\"&\" + beanName))
遍历includeFilters
获取包路径下所有class文件对象(注意不是class对象,可以理解为File对象)
有spring.components
执行这个bean的afterSingletonsInstantiated方法
registerBeanDefinition(核心代码在DefaultListableBeanFactory)
判断获得的bean是否实现SmartFactory且该bean的isEagerInit方法返回true
doscan(ClassPathBeanDefinitionScanner)
beandefinition是非抽象的而且是单例的,而且是非懒加载的
合并beandefinition得到RootBeanDefinition(getMergedLocalBeanDefinition)
匹配成功后生成一个ScannedGenericBeanDefinition
refresh ->finishBeanFactoryInitialization-> preInstantiateSingletons (实例化非懒加载单例bean)
遍历types,通过元数据读取器读来获取每个类的信息(最后下面的执行操作和普通的扫描时的操作是一样的)
扫描结束
1. 过滤掉excludeFilter,匹配includeFilter,最后再去判断Conditional注解2. Conditional注解有的话,去调用相应类的matches方法,true则通过,false则不通过
再次判断获得的bean是否是factorybean
如果当前的FactoryBean没有实现SmartFactoryBean,那么它就不会在初始化容器的时候就去调用getObject来创建bean,如果实现了该接口,就会像流程图所示会在初始化容器的时候去调用getObject来创建bean
条件成立
扫描
根据beanName来判断所对应的bean是否是factorybean(isFactoryBean(beanName))
最后再checkCandidate检查该beandefinition能否注册
最后再验证一遍beandefinition
给beanDefinition赋值scope、beanname等
没有
BeanDefinitionRegistry registry = AnnotationConfigApplicationConotext
AnnotationConfigApplicationContext中构建ClassPathBeanDefinitionScanner时,会设置一个默认注解@Component的includeFilter
有
利用ASM技术解析每个class文件对象得到class元数据信息
refresh(AnnotationConfigApplicationContext)
执行addCandidateComponentsFromIndex方法
遍历beanNames
没找到则去合并
0 条评论
下一页