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); } } }
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; }
以上是关于spring 初始化Bean的主要内容,如果未能解决你的问题,请参考以下文章
Spring Boot - 在初始化 DataSource bean 之前运行自定义代码
Spring中Bean初始化及销毁方法(InitializingBean接口DisposableBean接口@PostConstruct注解@PreDestroy注解以及init-method(代码片