持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第24天,点击查看活动详情
getBean(name);
-
转换beanname,首先把 传入的beandefinition的名称转换成真正的bean的名称;
-
getSingleton(beanName),从三级缓存中获取bean;
【说明】
getSingleton的重载有个参数:allowEarlyReference===这个参数是解决循环依赖的标记;
一级缓存 也就是单例缓存池 用于保存我们所有的单实例bean private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256); 三级缓存 该map用户缓存 key为 beanName value 为ObjectFactory(包装为早期对象) private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16); 二级缓存 ,用户缓存我们的key为beanName value是还未成熟的早期bean,还未赋值的bean private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);
执行该方法,先从一级缓存获取bean对象,一般来说,ioc容器中从一级缓存获取的bean是成熟的可以直接使用的;获取到bean直接返回;当首次加载时肯定是空的,因此走下面的逻辑;
一级缓存未get到bean, 并且系统会根据一个临时集合list,根据beanname判断是否正在创建这个bean;
private final Set<String> singletonsCurrentlyInCreation = Collections.newSetFromMap(new ConcurrentHashMap<>(16));去到二级缓存中查找,二级缓存的是早期的未赋值的bean 因此在方法的开始传参true是允许早期对象的存在,要是还不存在
从三级缓存中获取,三级缓存中获取 ObjectFactory对象 这就是用来解决循环依赖的关键,在ioc后期的过程中,当bean调用了构造方法的时候,把早期对象包裹成一个ObjectFactory暴露到三级缓存中;
三级缓存存在则通过getObject方法获取早期bean放到二级缓存,从三级缓存删除函数bean;
-
如果上面获取的Bean不是空,则继续判断当前bean的类型如果是普通bean则直接返回,如果是Factorybean则获取到真正的bean实例并返回;
判断当前bean是不是实现了beanInstance instanceof FactoryBean 或者是否是& 开头的;来确定是不是普通bean,还是工厂bean继续向下获得真正的bean实例;
-
获取单例bean getSingleton(beanName,o->{})
-
beforeSingletonCreation(beanName);
创建bean之前,把beanname添加到singletonsCurrentlyInCreation 正在创建当前bean的集合中;
-
createBean()-----》doCreateBean(相当复杂的一个方法)创建bean
-
afterSingletonCreation(beanName);
singletonsCurrentlyInCreation移除当前创建的beanname
-
addSingleton(beanName, singletonObject)
把创建出来的bean添加到一级缓存,从二三级缓存移除,添加到已注册的set集合中;
-
doCreateBean
首先就创建bean实例,creatbeanInstance();返回包装bean,从WrapperBean获取早期bean对象;
接下来就是判断这个bean是否是单例的,是否允许循环依赖,是否是正在创建的ben,满足上述的三个条件则把bean添加到三级缓存;
添加三级缓存:addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));首先是单例缓存池没有该对象然后把它添加到三级缓存;
三级缓存的FactoryObject通过函数式接口回调的方式添加:
//TODO
属性赋值populateBean
首先判断当前容器中有没有InstantiationAwareBeanPostProcessor类型的后置处理器,我们可以通过postProcessAfterInstantiation方法自定义一些bean的信息;
判断当前bean的注入方式:两种
AUTOWIRE_BY_NAME 根据名称注入
获得 bean的所有属性对象,循环判断该属性对象是不是引用类型,是的话则通过getBean的方式获取;
然后把bean之间互相的依赖关系注册起来; Map<String, Set> dependentBeanMap
AUTOWIRE_BY_TYPE 根据类型注入
初始化exposedObject = initializeBean()bean的赋值操作;
首先先进入invokeAwareMethods(beanName, bean)方法,判断是否实现了三个Aware接口;
强转成相应的类型执行set方法;
- BeanNameAware
- BeanClassLoaderAware
- BeanFactoryAware
然后再是
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName); //调用初始化方法 invokeInitMethods(beanName, wrappedBean, mbd); wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);