==> 学习汇总(持续更新)
==> 从零搭建后端基础设施系列(一)-- 背景介绍
接着上一篇【细品springboot源码】彻底弄懂spring bean的创建过程(上),说到了doCreateBean
这个方法,开始创建bean
,老规矩,贴关键代码,标号对着解释。
-
剖析创建Bean的源码
- 普通bean的创建过程三
接着往下运行,到了真正创建bean
的地方
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args) throws BeanCreationException { // Instantiate the bean. BeanWrapper instanceWrapper = null; if (mbd.isSingleton()) { //1.尝试从FactoryBean缓存中拿实例 instanceWrapper = this.factoryBeanInstanceCache.remove(beanName); } if (instanceWrapper == null) { //2.如果1没拿到,那么创建实例 instanceWrapper = createBeanInstance(beanName, mbd, args); } …… // Allow post-processors to modify the merged bean definition. synchronized (mbd.postProcessingLock) { if (!mbd.postProcessed) { try { //3.主要是将@Autowired和@Value标记的属性解析出来,提供给后续使用 applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName); } catch (Throwable ex) { …… } mbd.postProcessed = true; } } //4.判断是否允许提前暴露引用 // Eagerly cache singletons to be able to resolve circular references // even when triggered by lifecycle interfaces like BeanFactoryAware. boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences && isSingletonCurrentlyInCreation(beanName)); if (earlySingletonExposure) { //5.将bean提前加入缓存中 addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean)); } // Initialize the bean instance. Object exposedObject = bean; try { //6.本方法的重点,属性注入 populateBean(beanName, mbd, instanceWrapper); //7.初始化Bean exposedObject = initializeBean(beanName, exposedObject, mbd); } catch (Throwable ex) { …… } //8. if (earlySingletonExposure) { Object earlySingletonReference = getSingleton(beanName, false); if (earlySingletonReference != null) { if (exposedObject == bean) { exposedObject = earlySingletonReference; } else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) { String[] dependentBeans = getDependentBeans(beanName); Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length); for (String dependentBean : dependentBeans) { if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) { actualDependentBeans.add(dependentBean); } } if (!actualDependentBeans.isEmpty()) { …… } } } } // Register bean as disposable. try { //9.注册销毁bean的东西 registerDisposableBeanIfNecessary(beanName, bean, mbd); } catch (BeanDefinitionValidationException ex) { …… } return exposedObject; }
-
尝试从FactoryBean缓存中拿实例
为什么会有这一步呢?我们可以在当前文件下搜一下factoryBeanInstanceCache
这个属性在哪里用到了。因为代码太长,截图看不完,所以直接将该方法贴出来,并且省去无关部分。这个方法是做啥的呢?它只是为了做类型检查。@Nullable private FactoryBean<?> getSingletonFactoryBeanForTypeCheck(String beanName, RootBeanDefinition mbd) { synchronized (getSingletonMutex()) { //尝试从factoryBeanInstance缓存中拿(这里还不知道是不是FactoryBean) BeanWrapper bw = this.factoryBeanInstanceCache.get(beanName); if (bw != null) { //拿到就直接返回了(拿到了就确认是了) return (FactoryBean<?>) bw.getWrappedInstance(); } //如果factoryBeanInstanceCache中没有,那么尝试从单例缓存中拿 Object beanInstance = getSingleton(beanName, false); if (beanInstance instanceof FactoryBean) { //需要先判断是不是FactoryBean return (FactoryBean<?>) beanInstance; } //判断是不是正在创建,(是不是FactoryBean&是不是正在创建), if (isSingletonCurrentlyInCreation(beanName) || (mbd.getFactoryBeanName() != null && isSingletonCurrentlyInCreation(mbd.getFactoryBeanName()))) { return null; } Object instance; try { //这里只是标记一下正在创建 // Mark this bean as currently in creation, even if just partially. beforeSingletonCreation(beanName); //BeanPostProcessor大家都懂了 // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance. instance = resolveBeforeInstantiation(beanName, mbd); if (instance == null) { //如果BeanPostProcessor什么都没做,那么就正常的创建这个bean bw = createBeanInstance(beanName, mbd, null); instance = bw.getWrappedInstance(); } } catch (UnsatisfiedDependencyException ex) { // Don't swallow, probably misconfiguration... throw ex; } catch (BeanCreationException ex) { …… return null; } finally { //标记一下这个bean已经创建完成 // Finished partial creation of this bean. afterSingletonCreation(beanName); } //getFactoryBean里面很简单,就是判断一下instance是不是FactoryBean,不是的话就报错了 FactoryBean<?> fb = getFactoryBean(beanName, instance); if (bw != null) { //这里我也有个疑问,为什么fb不为null,bw为null的时候,不把instance放进来? this.factoryBeanInstanceCache.put(beanName, bw); } return fb; } }
-
如果1没拿到,那么创建实例
这个创建实例没啥好说的,有一个值得注意的地方是,如果是@Configuration
标记的类中的@Bean
创建,它有这么一段逻辑if (mbd.getFactoryMethodName() != null) { return instantiateUsingFactoryMethod(beanName, mbd, args); }
相当于代码中有这种
bean
的时候,会走instantiateUsingFactoryMethod
这个逻辑,感兴趣的可以看一下。@Configuration public class B { @Bean public F f(){ return new F(); } }
-
bean合并后的处理
主要是将@Autowired和@Value标记的属性解析出来,提供给后续使用。我们可以粗略的看一下代码。
然后看一下那个接口都在哪里被实现了,主要看一下划线的那个
像是在找什么信息
碍于篇幅,这里不细致讲下去了,推荐一篇文章MergedBeanDefinitionPostProcessor和@Autowired,@Value -
判断是否允许提前暴露引用
必须是单例,还要当前bean
正在创建中,例如A
创建的时候,需要创建B
,这时候,A
需要提前暴露引用,防止B
引用了A
,造成循环引用。 -
将bean提前加入缓存中
addSingletonFactory
就比较有趣了,可以看到,第二个参数是一个lambda
表达式,实际上代码是这样的addSingletonFactory(beanName, new ObjectFactory() { @Override public Object getObject() throws BeansException { return getEarlyBeanReference(beanName, mbd, bean); } });
再来看看spring随处可见的
getSingleton
方法@Nullable protected Object getSingleton(String beanName, boolean allowEarlyReference) { //先尝试从第一级缓存拿 Object singletonObject = this.singletonObjects.get(beanName); if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) { synchronized (this.singletonObjects) { //第一级没有,再尝试从第二级拿 singletonObject = this.earlySingletonObjects.get(beanName); if (singletonObject == null && allowEarlyReference) { //第二级还没有,那么尝试从第三级拿 ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName); if (singletonFactory != null) { //注意注意,这里调用getObject的时候,就会跳到刚才那里,去执行getEarlyBeanReference方法了 singletonObject = singletonFactory.getObject(); //然后将它放到第二级中 this.earlySingletonObjects.put(beanName, singletonObject); //第三级就应该删除了 this.singletonFactories.remove(beanName); } } } } return singletonObject; }
这下子知道spring的骚操作了吧
-
属性注入
这个就是doCreateBean
的重点了,所以放到下面单独拿出去讲 -
初始化Bean
为什么会有这一步呢?我们都知道,spring给了我们很多可扩展的接口,包括bean
实例化之前、实例化之后、初始化之前、初始化之后可以由我们自由控制。所以initializeBean
方法里,其实就是各种开放接口。可以简单看一下代码protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) { …… //1.调用实现了Aware接口的类的方法 invokeAwareMethods(beanName, bean); Object wrappedBean = bean; if (mbd == null || !mbd.isSynthetic()) { //2.初始化之前可以对bean干一些xxx事 wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName); } …… //3.调用bean的初始化方法 invokeInitMethods(beanName, wrappedBean, mbd); …… if (mbd == null || !mbd.isSynthetic()) { //4.初始化之后可以再对bean强行干一些xxx事 wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName); } return wrappedBean; }
这一块不展开讲,后续单独开一篇讲,还挺有意思的。
-
不知道是干啥的
就连书上的解释都懵懵懂懂,我给你们引用看一下,反正我是没懂,以后遇到再说吧。之前有提到过,在Sping中解决循环依赖只对单例有效,而对于prototype的bean,Spring没有好的解决办法,唯一要做的就是抛出异常。在这个步骤里面会检测已经加载的 bean 是否已经出现了依赖循环,并判断是否需要抛出异常。
-
注册销毁bean的东西
这个和初始化类似,到时候和它一起说
- 普通bean的创建过程四
最后,到属性注入了,革命的胜利就快来临了!
话不多说,源码走起
属性注入这一块,还有很多地方值得讲,在这么短的篇幅里也不能说的尽兴,所以创建protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) { …… //1.很显然,还要再给人家一次机会,在这个bean设置属性之前xxx这个bean // Give any InstantiationAwareBeanPostProcessors the opportunity to modify the // state of the bean before properties are set. This can be used, for example, // to support styles of field injection. boolean continueWithPropertyPopulation = true; if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) { for (BeanPostProcessor bp : getBeanPostProcessors()) { if (bp instanceof InstantiationAwareBeanPostProcessor) { InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp; if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) { continueWithPropertyPopulation = false; break; } } } } //2.漂亮,到这里了,还可以不让人家set属性 if (!continueWithPropertyPopulation) { return; } PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null); //3.如果设置了根据XX类型来查找bean注入,就会进入if循环,默认是AUTOWIRE_NO //这个我也很迷,我一直得到的灌输是,@Autowire是默认根据Type进行注入的(继续往代码里面看,确实是根据type进行注入的) int resolvedAutowireMode = mbd.getResolvedAutowireMode(); if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) { MutablePropertyValues newPvs = new MutablePropertyValues(pvs); // Add property values based on autowire by name if applicable. if (resolvedAutowireMode == AUTOWIRE_BY_NAME) { autowireByName(beanName, mbd, bw, newPvs); } // Add property values based on autowire by type if applicable. if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) { autowireByType(beanName, mbd, bw, newPvs); } pvs = newPvs; } boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors(); boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE); PropertyDescriptor[] filteredPds = null; if (hasInstAwareBpps) { if (pvs == null) { pvs = mbd.getPropertyValues(); } for (BeanPostProcessor bp : getBeanPostProcessors()) { if (bp instanceof InstantiationAwareBeanPostProcessor) { InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp; //4.设置属性之前的处理,在这里,会将需要注入的bean准备好 PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName); if (pvsToUse == null) { if (filteredPds == null) { filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching); } pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName); if (pvsToUse == null) { return; } } pvs = pvsToUse; } } } if (needsDepCheck) { if (filteredPds == null) { filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching); } checkDependencies(beanName, mbd, filteredPds, pvs); } if (pvs != null) { //5.将属性设置上去 applyPropertyValues(beanName, mbd, bw, pvs); } }
bean
的过程到这里就结束了吧。
- 普通bean的创建过程三
-
总结
- 创建
bean
的四个地方,顺序依次是prepareContext
、invokeBeanFactoryPostProcessors
、registerBeanPostProcessors
和preInstantiateSingletons
,其中前三个都是对那些特殊的bean
先进行创建,最后对普通的bean
进行创建。 - 在
preInstantiateSingletons
方法中可以知道,被@Lazy
标注的bean
不会被创建。想了解@Lazy
注解,可以看一下这篇【追根究底】@Lazy注解为什么会失效? - 整个创建
bean
的流程,可以看出spring命名方法的一些端倪,都是在doXXX方法中真正的去获取/创建 - 解决循环引用的地方是
doCreateBean
方法中,实例化bean
之后,将未初始化的bean
加入SingletonFactory
populateBean
属性注入,就是注入那些被@Autowired
和@Value
标注的属性- 创建
bean
的过程中,会有很多地方给BeanPostProcessor
机会,提前结束或者改变bean
的创建 - 其实
bean
的创建是递归的,属性注入的时候,也是bean
的创建。 - 其实
bean
的创建管理很简单,只是spring帮我们做了很多事,就像我们写很多ifelse那样,写多了,也就看起来复杂了。
- 创建
- 没涉及或者没细讲的点
createBean
中的prepareMethodOverrides
方法createBean
中的resolveBeforeInstantiation
方法doCreateBean
中的createBeanInstance
方法doCreateBean
中的applyMergedBeanDefinitionPostProcessors
方法doCreateBean
中的populateBean
方法doCreateBean
中的initializeBean
方法doCreateBean
中的registerDisposableBeanIfNecessary
方法
啊~,写之前以为能把所有都一次性讲清楚,但是一开始写,整理思路的时候,才知道,要把这些全写出来,得花好多时间,这代码也太复杂了点。看来只能慢慢以后再补充了。(自己懂是一回事,将自己懂的表述给别人,并且让别人懂,那真的又是一回事了,这时间膨胀得厉害啊!)
最后,有不懂的下方评论留言,我应该能答上来,哈哈!