Bean的创建过程
- refresh
- finishBeanFactoryInitialization
- preInstantiateSingletons
- getBean
- doGetBean
- 实例化
- 属性注入
- 初始化
总的过程就是这几步,下面详细走一下,从第三步开始
preInstantiateSingletons
该方法是在finishBeanFactoryInitialization方法中被执行。作用是实例化剩余的单实例bean
方法由DefaultListableBeanFactory实现
先获取ioc中的bean定义名称
List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
循环所有beanName,合并bean定义
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
其实就是先从缓存中拿beanDefinition,最终返回的是RootBeanDefinition,这里就牵扯到几种beanDefinition了。先挖个坑,后面再填
判断是不是抽象的、单例的、懒加载的 -->再是判断是不是工厂bean,是的话加上前缀符号。然后调用getBean
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
if (isFactoryBean(beanName)) {
//调用真正的getBean的流程
if (isEagerInit) {
getBean(beanName);
}
}
}
else {//非工厂Bean 就是普通的bean
getBean(beanName);
}
getBean会去调用doGetBean
首先尝试去一级缓存中拿,也就是第一次调用getSingleton方法。
当然bean本身没被创建,当然拿不到的,所以返回为空
Object sharedInstance = getSingleton(beanName);
下面就进入创建bean的逻辑
首先判断当前bean是否是正在创建中,且是原型的。是直接抛出异常。因为这里涉及到循环依赖的问题,而spring只能解决单例bean的setter注入循环依赖
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
随后是子父容器的判断。一般情况下只有spring和spring mvc整合的时候才会出现子父容器的概念
下面这段就先忽略
BeanFactory parentBeanFactory = getParentBeanFactory();
//若存在父工厂,切当前的bean工厂不存在当前的bean定义,那么bean定义是存在于父beanFacotry中
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
//获取bean的原始名称
String nameToLookup = originalBeanName(name);
//若为 AbstractBeanFactory 类型,委托父类处理
if (parentBeanFactory instanceof AbstractBeanFactory) {
return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
nameToLookup, requiredType, args, typeCheckOnly);
}
else if (args != null) {
// 委托给构造函数 getBean() 处理
return (T) parentBeanFactory.getBean(nameToLookup, args);
}
else {
// 没有 args,委托给标准的 getBean() 处理
return parentBeanFactory.getBean(nameToLookup, requiredType);
}
}
接着我们跳过各个校验直接来到创建单例bean
if (mbd.isSingleton()) {
//把beanName 和一个singletonFactory 并且传入一个回调对象用于回调
sharedInstance = getSingleton(beanName, () -> {
try {
//进入创建bean的逻辑
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
//创建bean的过程中发生异常,需要销毁关于当前bean的所有信息
destroySingleton(beanName);
throw ex;
}
});
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
这里调用getSingleton的重载方法。第二个参数是一个工厂接口
getSingleton
先加锁,然后再次试着从一级缓存中拿
Object singletonObject = this.singletonObjects.get(beanName);
还是为空,那就说明该bean需要创建,标注bean正在被创建,也就是加入到一个集合中singletonsCurrentlyInCreation
beforeSingletonCreation(beanName);
//该方法会进行判断是否集合中已经存在该bean,说明该bean正在被创建,会抛出异常
调用接口工厂的方法
try {
//<3> 初始化 bean
// 这个过程其实是调用 createBean() 方法
singletonObject = singletonFactory.getObject();
newSingleton = true;
}
也就是createBean()
createBean
方法前部分有一些验证,这里跳过。关键调用点是
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
所以spring中真正干活的还是do开头的
doCreateBean
if (instanceWrapper == null) {
//使用合适的实例化策略来创建新的实例:工厂方法、构造函数自动注入、简单初始化 该方法很复杂也很重要
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
doCreateBean中,这里利用反射之间创建bean实例
if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
//通过构造函数创建对象
return autowireConstructor(beanName, mbd, ctors, args);
}
//使用无参数的构造函数调用创建对象
return instantiateBean(beanName, mbd);
到这里bean已经被实例化了
然后穿插一下@Autowried注解的预解析
随即将刚刚实例化的bean进行早期暴露,条件是单例、允许早期暴露且是正在创建的bean
包装早期对象
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {
Assert.notNull(singletonFactory, "Singleton factory must not be null");
//同步加锁
synchronized (this.singletonObjects) {
//单例缓存池中没有包含当前的bean
if (!this.singletonObjects.containsKey(beanName)) {
//加入到三级缓存中,,,,,暴露早期对象用于解决循环依赖
this.singletonFactories.put(beanName, singletonFactory);
this.earlySingletonObjects.remove(beanName);
this.registeredSingletons.add(beanName);
}
}
}
将我们的bean加入到了三级缓存中
属性赋值
populateBean调用set方法进行赋值
populateBean(beanName, mbd, instanceWrapper);
初始化操作
exposedObject = initializeBean(beanName, exposedObject, mbd);
这里会调用三个关键的方法
applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
invokeInitMethods(beanName, wrappedBean, mbd);
applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
第一个是调用我们bean后置处理器的postProcessorsBeforeInitialization方法
第二个是初始化方法,这里会回调实现了 InitializingBean 接口的 afterPropertiesSet方法并且调用bean的init方法
第三个是调用bean后置处理器的postProcessorsAfterInitialization方法
完成之后bean才真正的算是创建完
善后处理
允许早期对象的调用,再次getSingleton,但是这次传递的allowEarlyReference是false
Object earlySingletonReference = getSingleton(beanName, false);
表示不再从三级缓存中拿,只会在一二级缓存中拿。注意,在此之前我们并未将bean放到一二级缓存中,只是放入了三级缓存。所以还是为空
注册销毁bean的接口
registerDisposableBeanIfNecessary(beanName, bean, mbd);
到此doCreateBean走完
方法弹栈,到最早调用getSingleton的地方,然后将该bean从正在创建的集合中剔除,也就是从singletonsCurrentlyInCreation中剔除。
afterSingletonCreation(beanName);
再加入到缓存中,将其加入到一级缓存,并二三级缓存中剔除,并添加入已处理bean集合中
addSingleton(beanName, singletonObject);
protected void addSingleton(String beanName, Object singletonObject) {
synchronized (this.singletonObjects) {
//加入到单例缓存池中
this.singletonObjects.put(beanName, singletonObject);
//从三级缓存中移除(针对的不是处理循环依赖的)
this.singletonFactories.remove(beanName);
//从二级缓存中移除(循环依赖的时候 早期对象存在于二级缓存)
this.earlySingletonObjects.remove(beanName);
//用来记录保存已经处理的bean
this.registeredSingletons.add(beanName);
}
}
总结
上述过程是一个普通bean的创建过程,没有循环依赖。
两次getSingleton
首先调用第一次getSingleton,也就是在doGetBean逻辑中调用的,这里调用的是传入接口工厂的重载
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
synchronized (this.singletonObjects) {
//尝试从单例缓存池中获取对象
Object singletonObject = this.singletonObjects.get(beanName);
beforeSingletonCreation(beanName);
try {
//<3> 初始化 bean
// 这个过程其实是调用 createBean() 方法
singletonObject = singletonFactory.getObject();
newSingleton = true;
}
finally {
if (recordSuppressedExceptions) {
this.suppressedExceptions = null;
}
// <4> 后置处理
//主要做的事情就是把singletonsCurrentlyInCreation标记正在创建的bean从集合中移除
afterSingletonCreation(beanName);
}
if (newSingleton) {
// <5> 加入缓存中
addSingleton(beanName, singletonObject);
}
}
return singletonObject;
}
}
在doCreateBean的逻辑里调用的,这个getSingleton作用上更加接近于我们正常下理解的,从一级缓存中拿,然后二级、三级
如果它能够在二级缓存中拿不到,并且是allowEarlyReference,允许早期暴露的。那么会从三级缓存中拿。拿到过后放入二级缓存,从三级缓存中删除
Object earlySingletonReference = getSingleton(beanName, false);
protected Object getSingleton(String beanName, boolean allowEarlyReference)
实例化和初始化期间穿插的后置处理器调用
在实例化之前,也就是调用doCreateBean之前,调用了下面的方法。这是AOP相关的
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
实例化完成之后,穿插了@Autowired注解的预解析工作
//进行后置处理 @AutoWired的注解的预解析
//MergedBeanDefinitionPostProcessor接口调用的入口
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
初始化之前,调用bean的后置处理器的beforeInitialization方法,也就是容器中所有实现了BeanPostProcessor的处理器
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
初始化之后,调用bean的后置处理器的AfterInitialization方法,也就是容器中所有实现了BeanPostProcessor的处理器
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);