Spring随笔(主要是bean加载)

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获取,这样就解决了循环依赖

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值