Spring随笔
bean的生命周期
注意:spring中的bean默认是单例模式
bean加载
源码逻辑分解图
主要方法 getBean
doGetBean(){
//获取给定名字注册的,缓存中的原始bean,
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
//校验bean的合法性,获取相应实例
getObjectForBeanInstance()
}else {
//如果缓存中没有,就要自己创建
//注册当前bean的依赖关系(依赖这个bean和这个bean依赖的)
registerDependentBean(dep, beanName);
//getSingleton的重写方法
getSingleton(beanName,()->{
try{
Return createBean(beanName,mbd,args);
}
}
缓存-单例对象getSingleton
指第一个getSingleton
单例在spring的同一容器中只会被创建一次,然后再获取bean直接从单例缓存中获取,当然,这里也只是尝试加载,首先尝试从缓存中加载,
然后再次尝试从singletonFactories中加载,因为在创建单例bean的时候会存在依赖注入的情况,而在创建依赖的时候为了避免循环依赖,
spring创建bean的原则是不等bean创建完成就会将创建bean的ObjectFactory提早曝光加入到缓存中,一旦下一个bean创建的时候依赖上个bean,则直接使用ObjectFactory
缓存-getObjectForBeanInstance
从bean的实例中获取对象
其实就是用于检测当前bean是否是FactoryBean类型的bean,如果是,那么需要调用该bean对应的FactoryBean实例中的getObject()作为返回值,随后从原始bean中获取最终想要的bean
getObjectForBeanInstance 中调用 getObjectFromFactoryBean() ,再调用doGetObjectFromFactoryBean()获得实例化的bean
新建-getSingleton
// 首先检查对应的bean是否已经加载过,因为singleton模式其实就是复用以创建的bean,所以这一步是必须的
Object singletonObject = this.singletonObjects.get(beanName);
// 如果为空才可以进行singleton的bean的初始化,即没有创建过
if (singletonObject == null) {
//将当前正要创建的bean记录在缓存中
beforeSingletonCreation(beanName);
//这个方法中传入的singletonFactory就是createBean里面的返回值,即加载好的bean
singletonObject = singletonFactory.getObject();
//将上面正在加载的记录移除出缓存
afterSingletonCreation(beanName);
//将结果记录至缓存并删除加载bean过程中所记录的各种辅助状态 同一个类中
addSingleton(beanName, singletonObject);
}
新建 - createBean
createBean实际上负责统筹管理工作,真正负责创建的是doCreateBean
createBean(){
//对override属性进行标记和验证
prepareMethodOverrides();
//实例化的前置处理函数,AOP的实现位置就在这。
//给予其他代码修改生成的bean的机会
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
}
doCreateBean
doCreateBean(){
instanceWrapper = createBeanInstance(beanName, mbd, args);
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
// 对bean进行填充,将各个属性值注入,其中,可能存在依赖于其他bean的属性,则会递归初始依赖bean
populateBean(beanName, mbd, instanceWrapper);
//循环依赖检查,此处不贴代码
// 初始化bean
exposedObject = initializeBean(beanName, exposedObject, mbd);
//注册bean的销毁方法扩展(可自定义销毁方案)
registerDisposableBeanIfNecessary(beanName, bean, mbd);
}
文字描述流程
1)如果是单例,则需要首先清除缓存
2)实例化bean,将BeanDefinition转换成BeanWrapper,转化是一个复杂过程,大致思路如下
如果存在工厂方法则使用工厂方法进行初始化
一个类有多个构造函数,每个构造函数都有不同的参数,所以需要根据参数锁定构造函数并进行初始化
如果即不存在工厂方法,也没有指定构造方法,则使用指定的构造方法初始化bean
(3)MergedBeanDefinitionPostProcessors的应用
bean合并后处理,autowire注解正是通过此方法实现注入类型的预解析
(4)依赖处理
(5)属性填充。将所有属性填充到bean的实例中
(6)循环依赖检查
在spring中解决循环依赖只对单例有效,而对于prototype的bean,spring没有更好的解决办法,唯一要做的是抛出异常。
(7)注册DisposableBean
如果配置了destroy-method,这里需要注册以便于在销毁时候调用
(8)完成创建并返回
createBeanInstance 构造函数实例化
//构造函数实例化
createBeanInstance(){
//根据不同的参数锁定是否为有参构造函数
if(mbd.resolvedConstructorOrFactoryMethod!=null){
resolved=true;
autowireNecessary=mbd.constructorArgumentsResolved;
}
//有参构造函数自动注入(If -else )
Return autowireConstructor(beanName,mbd,null,null);
//无参构造函数自动注入(If -else )
//用户没有使用replace或者lookup的配置方法,那么直接使用反射的方式,
//但是如果使用了这两个特性,则需要将这两个配置提供的功能切入进去
Return instantiateBean(beanName,mbd);
}
有参构造匹配
有参构造匹配很复杂:
①确定构造函数参数
②根据参数个数、参数类型、参数值确定构造函数
③转换参数类型(匹配参数、this等)
④构造函数不确定性验证
⑤将解析的参数加入缓存,实例化bean,
加入BeanInstance
populateBean属性注入 @autowire注解的实现
//属性自动注入(@autowire注解的实现)
populateBean (){
//根据名称注入
if(mbd.getResolvedAutowireMode()==AUTOWIRE_BY_NAME){
autowireByName(beanName,mbd,bw,newPvs);
}
//根据类型注入
if(mbd.getResolvedAutowireMode()==AUTOWIRE_BY_TYPE){
//为了满足可以注入集合,会加入局部遍历
autowireByType(beanName,mbd,bw,newPvs);
}
//后处理器初始化
booleanhasInstAwareBpps=hasInstantiationAwareBeanPostProcessors();
//对所有需要依赖的属性进行后处理
pvsToUse=ibp.postProcessPropertyValues(pvs,filteredPds,bw.getWrappedInstance(),beanName);
//将获取到的属性应用到bean中
applyPropertyValues(beanName,mbd,bw,pvs);
}
initializeBean 初始化
可用来调用用户自己定义的Init方法
initializeBean(){
//激活Aware方法
invokeAwareMethods(beanName, bean);
//前置处理方法,可以让用户定义自己的处理,并应用自己的处理
applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
//用于激活自定义的Init方法
//首先检测当前 bean 是否实现了 InitializingBean 接口,如果实现了则调用其afterPropertiesSet(),然后再检查是否也指定了 init-method(),如果指定了则通过反射机制调用指定的 init-method()
invokeInitMethods(beanName, wrappedBean, mbd);
//后置处理方法,可以让用户定义自己的处理
applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
循环依赖解决
spring容器将每一个正在创建的bean标识符放在一个“当前创建bean池”,bean标识符在创建过程中将一直保持在这个池中,因此如果在创建过程中发现自己已经在“当前创建bean池”中,将抛出异常表示循环依赖;而对于创建完毕的bean将从“当前创建bean池”中清除掉
在B中创建依赖A时通过ObjectFactory提供的实例方法来判断A中的属性填充,使B中持有A仅仅是刚刚初始化并没有填充任何属性A,但是因为A和B中的A所表示的属性地址是一样的,所以在A中创建好的属性填充自然可以通过B中的A获取,这样就解决了循环依赖