spring 初始化Bean

Posted soft.push("zzq")

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了spring 初始化Bean相关的知识,希望对你有一定的参考价值。

说起spring bean的初始化自然而然就离不开初始化阶段的循环引用;
1 首先spring容器在启动后会创建一个beanFactory,new DefaultListableBeanFactory。

2 然后在spring容器启动过程中会调用核心的refresh方法,在这个方法中共调用了9个方法,即为spring容器的初始过程,所以说spring容器不单单是我们狭义概念中的map那么简单,在这个方法中包含两个最最主要的方法:

2.1 invokeBeanFactoryPostProcessors(beanFactory)
      在这个方法中,会调用spring的beanFactory后置处理器,将所有扫描到要注册为Bean的javaClass信息收集后,构建成BeanDefinition,后register到beanDefinitionMap中,为以后Bean的初始化提供信息。

2.2 finishBeanFactoryInitialization(beanFactory)
      该方法显得更加额外的重要,在这个方法的最后阶段会调用preInstantiateSingletons,很明显在这个方法中我们要初始化Scope为single的bean,而原型bean则不需要单独做处理, 因为原型bean无论是初始化阶段还是注入阶段都是直接创建“对象或者代理对象”
     preInstantiateSingletons方法中调用了getBean方法,之后使用了委托模式调用了doGetBean方法。doGetBean方法中调用了两次getSingleton方法,并且经过了3个缓存Map(singleObjectMap,singletonFactory,earlySingleObjects),两次调用的本质就是解决循环引用的问题;因为如果不存在循环引用的话就会直接调用creatBean方法去走bean的创建流程了。

      话又说回来,第一次调用getSingleton的时候直接指定了循环引用为true,进入第二个getSingleton方法;
       (1)会先从bean的缓存池中获取创建好的bean对象,但是一定是获取失败的,因为bean没有走完生命周期的创建过程。
       (2)会在从earlySingletonObject缓存Map中去拿,因为首次创建刚刚进行,该Bean还没有被标记为“创建状态”所以仍然无法获取。
       (3)两次获取失败后,就会调用第三种getSingleton方法,通过lambda表达式中的createBean方法去走实际创建对象的过程了,在执行createBean之前有个重要的环节就是当 前的初始状态Bean已经被加入到“创建状态的集合中”,并且已经将创建bean的工厂放入了singletonFactoriesMap缓存集合中。

 public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
        Assert.notNull(beanName, "‘beanName‘ must not be null");
        Map var3 = this.singletonObjects;
        synchronized(this.singletonObjects) {
            Object singletonObject = this.singletonObjects.get(beanName);
            if(singletonObject == null) {
                if(this.singletonsCurrentlyInDestruction) {
                    throw new BeanCreationNotAllowedException(beanName, "Singleton bean creation not allowed while singletons of this factory are in destruction (Do not request a bean from a BeanFactory in a destroy method implementation!)");
                }

                if(this.logger.isDebugEnabled()) {
                    this.logger.debug("Creating shared instance of singleton bean ‘" + beanName + "‘");
                }

                this.beforeSingletonCreation(beanName);
                boolean newSingleton = false;

 

protected void beforeSingletonCreation(String beanName) {
if(!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.add(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
}

3 在createBean方法中仍然通过委托模式继续调用doCreateBean方法,doCreateBean方法中也有2了核心方法:

3.1 createInstance会创建出一个java类本身的wapper对象;

if(instanceWrapper == null) {
instanceWrapper = this.createBeanInstance(beanName, mbd, args);
}

3.2 populateBean方法会将包装对象中带有Bean注解的成员变量进行注入
      在这个方法中会去装配autowire注解的对象,这个时候会继续调用getBean方法,然后再次调用getSingleton方法,执行之前的一系列重复createBean操作。
      那么此时应该注意,循环依赖发生后,注入属性对象仍然会持有原来对象,但是原来对象在调用第二次getSingleton方法时,已经可以通过二级缓存中的singleFactoryMap获取到Factory,并实例化Bean放入到earlySingleObjectMap三级缓存中,从而获取到对象。这样循环依赖就不会造成死循环循环创建了。(这里二级缓存工厂,作用就是可能返回原对象或发生AOP之后的增强代理对象,实质是由Bean的后置处理器执行后的结果)

技术图片
protected void populateBean(String beanName, RootBeanDefinition mbd, BeanWrapper bw) {
PropertyValues pvs = mbd.getPropertyValues();
if(bw == null) {
if(!((PropertyValues)pvs).isEmpty()) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
}
} else {
boolean continueWithPropertyPopulation = true;
if(!mbd.isSynthetic() && this.hasInstantiationAwareBeanPostProcessors()) {
Iterator var6 = this.getBeanPostProcessors().iterator();

while(var6.hasNext()) {
BeanPostProcessor bp = (BeanPostProcessor)var6.next();
if(bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor)bp;
if(!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
continueWithPropertyPopulation = false;
break;
}
}
}
}

if(continueWithPropertyPopulation) {
if(mbd.getResolvedAutowireMode() == 1 || mbd.getResolvedAutowireMode() == 2) {
MutablePropertyValues newPvs = new MutablePropertyValues((PropertyValues)pvs);
if(mbd.getResolvedAutowireMode() == 1) {
this.autowireByName(beanName, mbd, bw, newPvs);
}

if(mbd.getResolvedAutowireMode() == 2) {
this.autowireByType(beanName, mbd, bw, newPvs);
}

pvs = newPvs;
}

boolean hasInstAwareBpps = this.hasInstantiationAwareBeanPostProcessors();
boolean needsDepCheck = mbd.getDependencyCheck() != 0;
if(hasInstAwareBpps || needsDepCheck) {
PropertyDescriptor[] filteredPds = this.filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
if(hasInstAwareBpps) {
Iterator var9 = this.getBeanPostProcessors().iterator();

while(var9.hasNext()) {
BeanPostProcessor bp = (BeanPostProcessor)var9.next();
if(bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor)bp;
pvs = ibp.postProcessPropertyValues((PropertyValues)pvs, filteredPds, bw.getWrappedInstance(), beanName);
if(pvs == null) {
return;
}
}
}
}

if(needsDepCheck) {
this.checkDependencies(beanName, mbd, filteredPds, (PropertyValues)pvs);
}
}

this.applyPropertyValues(beanName, mbd, bw, (PropertyValues)pvs);
}
}
}
View Code

3.3 属性装配结束后调用initializeBean方法就是去调用Bean实现的接口回调函数,也就是一系列的Bean后置处理器方法。

技术图片
protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
if(System.getSecurityManager() != null) {
AccessController.doPrivileged(new PrivilegedAction<Object>() {
public Object run() {
AbstractAutowireCapableBeanFactory.this.invokeAwareMethods(beanName, bean);
return null;
}
}, this.getAccessControlContext());
} else {
this.invokeAwareMethods(beanName, bean);
}

Object wrappedBean = bean;
if(mbd == null || !mbd.isSynthetic()) {
wrappedBean = this.applyBeanPostProcessorsBeforeInitialization(bean, beanName);
}

try {
this.invokeInitMethods(beanName, wrappedBean, mbd);
} catch (Throwable var6) {
throw new BeanCreationException(mbd != null?mbd.getResourceDescription():null, beanName, "Invocation of init method failed", var6);
}

if(mbd == null || !mbd.isSynthetic()) {
wrappedBean = this.applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}

return wrappedBean;
}
View Code

 

以上是关于spring 初始化Bean的主要内容,如果未能解决你的问题,请参考以下文章

Spring在代码中获取bean的几种方式(转)

Spring Boot - 在初始化 DataSource bean 之前运行自定义代码

Spring中Bean初始化及销毁方法(InitializingBean接口DisposableBean接口@PostConstruct注解@PreDestroy注解以及init-method(代码片

Spring课程 Spring入门篇 3-2 Spring bean装配(上)之bean的生命周期

如何获取容器中的bean对象

获取Spring的Bean