Bean生命周期
2020-09-17 17:15:06 0 举报
AI智能生成
spring bean生命周期
作者其他创作
大纲/内容
BeanDefinition的注册
1.在Context的构造器中的第一行代码注册了几个重要的BeanDefinition,
红色的子项为必定会注册的BeanDefinition
红色的子项为必定会注册的BeanDefinition
1.注册ConfigurationClassPostProcessor
2.注册AutowiredAnnotationBeanPostProcessor
3.注册RequiredAnnotationBeanPostProcessor
4.如果支持JSR-250,注册CommonAnnotationBeanPostProcessor
5.如果支持jpa,注册PersistenceAnnotationBeanPostProcessor
6.注册EventListenerMethodProcessor
7.注册DefaultEventListenerFactory
2.在Context构造器中调用refresh方法时,在refresh方法内部又调用了
invokeBeanFactoryPostProcessors方法,这里完成了所有的BeanDefinition的注册
invokeBeanFactoryPostProcessors方法,这里完成了所有的BeanDefinition的注册
1.ConfigurationClassPostProcessor处理器的
postProcessBeanDefinitionRegistry方法
postProcessBeanDefinitionRegistry方法
1.用BeanFactory生成一个注册表ID将id添加到set集合,
表明该工厂已经处理过了,说明只处理一次
表明该工厂已经处理过了,说明只处理一次
2.调用processConfigBeanDefinitions方法
1.得到工厂中所有已经存在的BeanDefinition的名称
2.遍历这些BeanDefinition的名称,从中筛选出配置类
3.如果经过筛选没有找到配置类,则直接return
4.如果找到配置类,根据@Order对这些配置进行排序
5.创建ConfigurationClassParser对象,
并将找到的配置类放到一个Set中去重
并将找到的配置类放到一个Set中去重
6.触发一个循环,根据candidates是否为空循环处理
1.调用ConfigurationClassParser的parse方法
1.遍历传入的配置类Definition的集合
2.将每一个配置类的元信息封装到ConfigurationClass对象中,
分别调用processConfigurationClass方法进行处理
分别调用processConfigurationClass方法进行处理
1.判断解析器是否已经解析过这个配置类了,如果已经解析过了,
就根据条件判断是否需要进行覆盖
就根据条件判断是否需要进行覆盖
2.将configClass封装成SourceClass,
然后进入一个循环,循环条件是sourceClass不为空,
循环中调用doProcessConfigurationClass进行真正的处理,
循环中调用的方法的第八步会返回当前类的父类,实现循环调用
然后进入一个循环,循环条件是sourceClass不为空,
循环中调用doProcessConfigurationClass进行真正的处理,
循环中调用的方法的第八步会返回当前类的父类,实现循环调用
1.调用processMemberClasses递归处理内部类
2.处理@PropertySources跟@PropertySource注解,
将对应的属性资源添加容器中(实际上添加到environment中)
将对应的属性资源添加容器中(实际上添加到environment中)
3.处理@ComponentScan,@ComponentScans注解
在子项中分析一下ComponentScanAnnotationParser的
parse方法的执行流程,ComponentScanAnnotationParser就是
当前ConfigurationClassParse的一个成员变量,
注意,如果子项返回的BeanDefinition中有配置类,直接调用processConfigurationClass处理
在子项中分析一下ComponentScanAnnotationParser的
parse方法的执行流程,ComponentScanAnnotationParser就是
当前ConfigurationClassParse的一个成员变量,
注意,如果子项返回的BeanDefinition中有配置类,直接调用processConfigurationClass处理
1.创建一个ClassPathBeanDefinitionScanner对象
2.解析成BeanDefinition时采用的beanName的生成规则
3.配置这个扫描注解规则下的ScopedProxyMode
和ScopeMetadataResolver
和ScopeMetadataResolver
4.配置扫描器的匹配规则
5.配置扫描器需要扫描的组件的类型过滤器
6.配置扫描器不需要扫描的组件类型过滤器
7.配置默认是否进行懒加载
8.配置扫描器扫描的包名
9.添加排除过滤器过滤当前@ComponentScan所在类
10.在完成对扫描器的配置后,直接调用其doScan方法进行扫描
1.调用findCandidateComponents方法,
得到ScannedGenericBeanDefinition集合
得到ScannedGenericBeanDefinition集合
2.遍历集合
1.判断BeanDefinition是不是AbstractBeanDefinition类型的,
如果是就执行postProcessBeanDefinition方法
如果是就执行postProcessBeanDefinition方法
2.判断是不是一个AnnotatedBeanDefinition,
如果是的话,还需要进行额外的处理
如果是的话,还需要进行额外的处理
3.检查容器中是否已经有这个bd了,如果没有就进行注册
3.返回扫描得到的BeanDefinition集合
11.返回扫描得到的BeanDefinition集合
4.处理@Import注解
1.递归遍历sourceClass得到所有的@Import注解的值作为一个参数传入
2.首先检查是否是循环引入,如果是循环引入,则不处理,只记录到错误日志中
3.如果检查没有问题,先将当前的这个配置类压入导入栈中,
遍历传入的@Import注解的值的Set集合,子项中是循环体
遍历传入的@Import注解的值的Set集合,子项中是循环体
1.如果遍历的元素是ImportSelector类型的
2.如果是一个ImportBeanDefinitionRegistrar
3.既不是一个ImportSelector也不是一个ImportBeanDefinitionRegistrar,
直接导入一个普通类并将这个类作为配置类,
调用processConfigurationClass进行递归处理
直接导入一个普通类并将这个类作为配置类,
调用processConfigurationClass进行递归处理
4.在循环前我们将其加入了导入栈中,循环完成后将其弹出,主要是为了处理循环导入
5.处理@ImportResource注解
6.处理@Bean注解
7.处理接口中的default方法
8.返回当前类的父类,进行递归处理
3.解析完成后,把解析过的configClass添加到解析器的
configurationClasses(Map)集合中
configurationClasses(Map)集合中
2.调用ConfigurationClassParser的validate方法
3.将通过解析@Bean,@Import等注解得到相关信息解析成bd注入到容器中
4.接着将处理过的配置类加入到已处理的配置类Set集合中,
避免重复处理
避免重复处理
5.经过前面的解析处理,会有很多新的BeanDefinition加入到容器中,
这时需要比较处理前后容器中BeanDefinition数量是否有增加,
如果有增加,得到这些BeanDefinition重新循环进行处理
这时需要比较处理前后容器中BeanDefinition数量是否有增加,
如果有增加,得到这些BeanDefinition重新循环进行处理
7.注册ImportRegistry到容器中
2.ConfigurationClassPostProcessor处理器的
postProcessBeanFactory方法
postProcessBeanFactory方法
实例化阶段
实例化前
1.refresh方法中调用beanFactory.preInstantiateSingletons()
2.preInstantiateSingletons方法中调用getBean
3.getBean方法中调用doGetBean
4.doGetBean方法中调用getSingleton(String beanName, ObjectFactory<?> singletonFactory)方法,
得到单例bean的早期引用,这里的实现方法是通过出入一个ObjectFactory类型的参数,spring在实现的时候用的
是lamda表达式,该参数的实现中调用了createBean方法,该方法完成bean的创建,
这个方法由AbstractAutowireCapableBeanFactory实现
得到单例bean的早期引用,这里的实现方法是通过出入一个ObjectFactory类型的参数,spring在实现的时候用的
是lamda表达式,该参数的实现中调用了createBean方法,该方法完成bean的创建,
这个方法由AbstractAutowireCapableBeanFactory实现
5.createBean方法中解析BeanDefinition中的beanClass属性
6.createBean方法中处理lookup-method跟replace-method,
判断是否存在方法的重载
判断是否存在方法的重载
3.createBean方法中判断这个类在之后是否需要进行AOP代理
实例化
1.doCreateBean方法中:单例情况下,看factoryBeanInstanceCache这个缓存中是否有
2,doCreateBean方法中:如果没有,创建Bean对象(这里实例化调用的是createBeanInstance方法),
并且将对象包裹在BeanWrapper中
并且将对象包裹在BeanWrapper中
1.通过Supplier实例化
2.通过静态工厂方法或者实例工厂方法实例化,
这里通过调用instantiateUsingFactoryMethod
方法实现,方法内部是创建一个ConstructorResolver,
并将实际的实例化工作交给它的方法
instantiateUsingFactoryMethod来处理
这里通过调用instantiateUsingFactoryMethod
方法实现,方法内部是创建一个ConstructorResolver,
并将实际的实例化工作交给它的方法
instantiateUsingFactoryMethod来处理
1.创建并初始话一个BeanWrapperImpl
2.如果是静态工厂就得到静态工厂Class,
如果是实例工厂还要实例化这个工厂对象
如果是实例工厂还要实例化这个工厂对象
3.如果创建的是原型对象spring做了优化处理,
单例对象不会经过这一步
单例对象不会经过这一步
4.得到创建对象使用的工厂方法及参数,并进行缓存
5.反射调用方法实例化对象
3.通过构造函数实例化
1.首先是判断构造器参数是否已经解析过了,
这里也是只有在原型模式下才会有用
这里也是只有在原型模式下才会有用
2.进行构造函数推断,得到所有满足条件的构造函数集合
3.如果经过推断返回的集合中有构造函数,
则调用autowireConstructor方法
则调用autowireConstructor方法
4.否则调用默认的构造函数
实例化后
1.从BeanWrapper中得到刚刚实例化的BeanWrappper对象,赋值给bean变量
2.应用MergedBeanDefinitionPostProcessor类型的后处理器,
主要是收集当前处理的BeanDefinition的注入点数据封装成InjectedElement
主要是收集当前处理的BeanDefinition的注入点数据封装成InjectedElement
3.根据是否是单例,添加一个lamda表达式到三级缓存中,同时删除二级缓存,
这里这步操作是为了暴露一个早期的对象引用来解决循环引用的问题
这里这步操作是为了暴露一个早期的对象引用来解决循环引用的问题
属性注入阶段
1.将原始对象赋值给exposedObject
2.调用populateBean方法进行属性注入
1.处理NullBean
2.如果当前BeanDefinition不是合成的,
应用InstantiationAwareBeanPostProcessor的实例化后方法
应用InstantiationAwareBeanPostProcessor的实例化后方法
3.判断是否开启了自动注入,
自动注入分为byName和byType
自动注入分为byName和byType
1.autowireByName
2.autowireByType
4.检查是否有InstantiationAwareBeanPostProcessor,
这种类型的后处理器完成了属性注入
这种类型的后处理器完成了属性注入
5.是否需要依赖检查
6.根据前两个判断进行if块中
1.如果有InstantiationAwareBeanPostProcessor
2.如果需要进行依赖检查,
调用checkDependencies方法
调用checkDependencies方法
7.将XML中的配置属性应用到Bean上
初始化阶段
调用initializeBean方法
1.第一步:执行aware接口中的方法
2.applyBeanPostProcessorsBeforeInitialization
3.调用invokeInitMethods,完成初始化方法执行
1.如果实现了InitializingBean接口,
则首先调用该接口的afterPropertiesSet方法
则首先调用该接口的afterPropertiesSet方法
2.调用自定义的初始化方法
4.applyBeanPostProcessorsAfterInitialization
5.这里返回传入的exposedObject对象,这里注意该对象可能被在第四步执行后变成代理对象
如果允许提前暴露bean,这里会进行检查,
保证最终bean的一致性
保证最终bean的一致性
注册需要销毁的Bean,放到一个需要销毁的Map中
销毁阶段
0 条评论
下一页