1 Bean实例化
紧接着上文,Spring的Bean实例化发生在刷新IOC容器阶段的倒数第二步finishBeanFactoryInitialization(beanFactory),最终在该方法中调用DefaultListable.preInstantiateSingletons()方法实例化所有非懒加载的Bean实例,代码如下
代码语言:javascript复制public void preInstantiateSingletons() throws BeansException {
......
List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
// 加载所有非懒加载的Bean
for (String beanName : beanNames) {
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
if (isFactoryBean(beanName)) {
Object bean = getBean(FACTORY_BEAN_PREFIX beanName);
if (bean instanceof FactoryBean) {
// 如果是FactoryBean,先判断是不是需要在此处实例化,需要才实例化
FactoryBean<?> factory = (FactoryBean<?>) bean;
boolean isEagerInit;
if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
isEagerInit = AccessController.doPrivileged(
(PrivilegedAction<Boolean>) ((SmartFactoryBean<?>) factory)::isEagerInit,
getAccessControlContext());
}
else {
isEagerInit = (factory instanceof SmartFactoryBean &&
((SmartFactoryBean<?>) factory).isEagerInit());
}
if (isEagerInit) {
getBean(beanName);
}
}
}
else {
getBean(beanName);
}
}
}
// 所有非懒加载Bean实例加载完成之后,Bean如果实现了SmartInitializingSingleton,调用其回调方法
// afterSingletonsInstantiated(),这个特性在xxl-job执行器的初始化中有使用过
for (String beanName : beanNames) {
Object singletonInstance = getSingleton(beanName);
if (singletonInstance instanceof SmartInitializingSingleton) {
StartupStep smartInitialize = getApplicationStartup().start("spring.beans.smart-initialize")
.tag("beanName", beanName);
SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
smartSingleton.afterSingletonsInstantiated();
return null;
}, getAccessControlContext());
}
else {
smartSingleton.afterSingletonsInstantiated();
}
smartInitialize.end();
}
}
}
代码也比较清晰,第一步实例化所有非懒加载的实例,其核心就是调用getBean(beanName)方法,第二步如果Bean实现了SmartInitializingSingleton接口,调用其回调方法afterSingletonsInstantiated(),而getBean方法是调用AbstractBeanFactory.doGetBean方法,doGetBean方法的代码比较复杂,以一个循环依赖且是单例模式的例子来梳理代码的流程(A依赖B,B依赖A,A,B都是单例模式),如下只保留了核心代码的流程
代码语言:javascript复制protected <T> T doGetBean(
String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
throws BeansException {
String beanName = transformedBeanName(name);
Object beanInstance;
// 第一步,先从缓存中获取Bean实例
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
......
beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, null);
} else {
......
StartupStep beanCreation = this.applicationStartup.start("spring.beans.instantiate")
.tag("beanName", name);
try {
......
RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);
// 第二步,检查Bean依赖
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
for (String dep : dependsOn) {
if (isDependent(beanName, dep)) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Circular depends-on relationship between '" beanName "' and '" dep "'");
}
registerDependentBean(dep, beanName);
try {
getBean(dep);
}
catch (NoSuchBeanDefinitionException ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"'" beanName "' depends on missing bean '" dep "'", ex);
}
}
}
// 第三步,创建Bean
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, () -> {
try {
return createBean(beanName, mbd, args);
} catch (BeansException ex) {
destroySingleton(beanName);
throw ex;
}
});
beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
} else if (mbd.isPrototype()) {
......
} else {
......
}
} catch (BeansException ex) {
......
} finally {
beanCreation.end();
}
}
return adaptBeanInstance(name, beanInstance, requiredType);
}
下面就一步一步来分析
第一步:首先调用getSingleton(beanName)从缓存中获取A实例,如下
代码语言:javascript复制public Object getSingleton(String beanName) {
return getSingleton(beanName, true);
}
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
// Quick check for existing instance without full singleton lock
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null && allowEarlyReference) {
synchronized (this.singletonObjects) {
// Consistent creation of early reference within full singleton lock
singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null) {
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
singletonObject = singletonFactory.getObject();
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
}
}
}
}
}
}
return singletonObject;
}
从上面的代码中可以看出,Spring用了三级缓存来处理
第一级缓存singletonObjects,是一个Map<String, Object>结构,key是BeanName,value是Instance,先从singletonObjects中获取实例,如果实例不为空,直接返回,所以这里先实例化A的时候,A为空且不在创建当中(创建中的实例用singletonsCurrentlyInCreation这个Set结构来保存),直接返回null
第二步:检查依赖,第一步返回null,则走到创建Bean的流程,创建Bean之前,首先要检查Bean依赖于哪些Bean,这里的依赖并不是指@Autowired这类属性注入的依赖关系,而是@DependsOn这类注解配置的依赖,如果有依赖,则先实例化DependsOn的Bean,如果没有就开始第三步创建Bean
第三步:创建Bean,调用了getSingleton(String beanName, ObjectFactory<?> singletonFactory)方法,代码如下
代码语言:javascript复制public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
......
synchronized (this.singletonObjects) {
// 还是先从第一级缓存singletonObjects中获取实例,不为null直接返回
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
// 在创建的过程当中,如果Bean正处于销毁中,则抛出异常
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!)");
}
......
// 执行创建之前的操作,其实就是将该Bean标记为创建中的状态,也就是将BeanName放入到上面提到过的
// singletonsCurrentlyInCreation这个Set结构中
beforeSingletonCreation(beanName);
boolean newSingleton = false;
boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
if (recordSuppressedExceptions) {
this.suppressedExceptions = new LinkedHashSet<>();
}
try {
// 通过singletonFactory创建Bean
singletonObject = singletonFactory.getObject();
newSingleton = true;
}
catch (IllegalStateException ex) {
......
} catch (BeanCreationException ex) {
......
} finally {
......
// 执行创建之后的操作,即将BeanName从singletonsCurrentlyInCreation这个Set结构中删除
afterSingletonCreation(beanName);
}
if (newSingleton) {
// 将生成的Bean放入到第一级缓存singletonObjects当中,并且删除第二级和第三级缓存
addSingleton(beanName, singletonObject);
}
}
return singletonObject;
}
}
说明都放在了上面的代码注释中,下面再来看看singletonFactory创建Bean的过程,是通过调用createBean(beanName, mbd, args)方法创建,代码如下
代码语言:javascript复制protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
......
RootBeanDefinition mbdToUse = mbd;
......
try {
// 执行Bean实例化之前的操作,即依次执行InstantiationAwareBeanPostProcessor的postProcessBeforeInstantiation方法
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
// 如果在postProcessBeforeInstantiation方法中返回了实例,直接返回
if (bean != null) {
return bean;
}
} catch (Throwable ex) {
......
}
try {
// 创建实例
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
if (logger.isTraceEnabled()) {
logger.trace("Finished creating instance of bean '" beanName "'");
}
return beanInstance;
}
catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
......
} catch (Throwable ex) {
......
}
}
从上面的代码中可以看出createBean的方法比较简单,就是在创建实例之前先依次执行InstantiationAwareBeanPostProcessor的postProcessBeforeInstantiation方法,然后再调用doCreateBean(beanName, mbdToUse, args)方法创建实例,看看doCreateBean方法
代码语言:javascript复制protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
// 1.实例化bean.
BeanWrapper instanceWrapper = null;
......
if (instanceWrapper == null) {
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
......
// 2.封装一个Bean创建工厂放入第三级缓存singletonFactories
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
if (logger.isTraceEnabled()) {
logger.trace("Eagerly caching bean '" beanName
"' to allow for resolving potential circular references");
}
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
Object exposedObject = bean;
try {
// 3.设置Bean属性
populateBean(beanName, mbd, instanceWrapper);
// 4.初始化Bean
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
catch (Throwable ex) {
if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
throw (BeanCreationException) ex;
}
else {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
}
}
// 5.设置exposedObject
if (earlySingletonExposure) {
Object earlySingletonReference = getSingleton(beanName, false);
if (earlySingletonReference != null) {
if (exposedObject == bean) {
exposedObject = earlySingletonReference;
}
......
}
}
return exposedObject;
}
doCreateBean方法的逻辑也比较清晰,主要有以下的步骤,依次来看看
1.实例化bean,这一步没啥好说的,主要就是创建一个Bean实例
2.如果允许循环依赖并且是在创建中的状态,就封装一个Bean创建工厂放入第三级缓存singletonFactories,singletonFactories也是一个Map结构,这个创建工厂并不是创建Bean的实例(第一步已经做了),而是在第一步创建的Bean的基础上做一层或者多层封装
3.设置Bean属性,主要通过populateBean(beanName, mbd, instanceWrapper)方法来执行,代码如下
代码语言:javascript复制protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
......
// 首先执行InstantiationAwareBeanPostProcessor的postProcessAfterInstantiation方法
// 即在Bean实例化之后需要执行的方法
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
if (!bp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
return;
}
}
}
......
// 再次执行InstantiationAwareBeanPostProcessor的各种后置处理方法
// @AutoWire注解就是在此处通过AutowiredAnnotationBeanPostProcessor这个类处理的
boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);
PropertyDescriptor[] filteredPds = null;
if (hasInstAwareBpps) {
if (pvs == null) {
pvs = mbd.getPropertyValues();
}
for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
PropertyValues pvsToUse = bp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
if (pvsToUse == null) {
if (filteredPds == null) {
filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
}
pvsToUse = bp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
if (pvsToUse == null) {
return;
}
}
pvs = pvsToUse;
}
}
......
}
由于A依赖B,所以在populateBean方法中又会重新调用doGetBean方法获取B的实例,在B实例的实例化过程中同样的逻辑重新执行一遍又到populateBean方法,由于B又依赖于A,所以在populateBean方法中又会去获取A实例,所有这里我们再来看看getSingleton(beanName,true)方法,如下
代码语言:javascript复制protected Object getSingleton(String beanName, boolean allowEarlyReference) {
// Quick check for existing instance without full singleton lock
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null && allowEarlyReference) {
synchronized (this.singletonObjects) {
// Consistent creation of early reference within full singleton lock
singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null) {
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
singletonObject = singletonFactory.getObject();
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
}
}
}
}
}
}
return singletonObject;
}
这里和第一次获取A的逻辑不同,这依次会走到第三级缓存singletonFactories这里,通过之前创建的工厂来生成A的实例,即通过getEarlyBeanReference(beanName, mbd, bean)方法来生成最终的A实例,如下
代码语言:javascript复制protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
Object exposedObject = bean;
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (SmartInstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().smartInstantiationAware) {
exposedObject = bp.getEarlyBeanReference(exposedObject, beanName);
}
}
return exposedObject;
}
这里就不得不提到AnnotationAwareAspectJAutoProxyCreator这个BeanPostProcessor了,如果我们的类有切面,就是通过AnnotationAwareAspectJAutoProxyCreator来生成的代理类,这样最终A的实例就生成了,最后再将A的创建工厂从第三级缓存singletonFactories中删除,再放入到第二级缓存earlySingletonObjects中,这样就完成了B实例中的A的依赖注入
4.初始化Bean
最后一步通过initializeBean(beanName, exposedObject, mbd)方法进行初始化,如下
代码语言:javascript复制protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
// 执行各种Aware接口的注入,这一步处理的Aware主要有BeanNameAware、BeanClassLoaderAware、
// BeanFactoryAware
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
invokeAwareMethods(beanName, bean);
return null;
}, getAccessControlContext());
}
else {
invokeAwareMethods(beanName, bean);
}
// 执行BeanPostProcessor的postProcessBeforeInitialization方法
// 即在初始化之前要执行的方法
// 其中像@PostConstruct注解的方法就是在此处执行
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
try {
// 执行初始化的方法,先执行InitializingBean的接口方法afterPropertiesSet,再执行配置的init方法
invokeInitMethods(beanName, wrappedBean, mbd);
}
catch (Throwable ex) {
throw new BeanCreationException(
(mbd != null ? mbd.getResourceDescription() : null),
beanName, "Invocation of init method failed", ex);
}
// 执行BeanPostProcessor的postProcessAfterInitialization
// 即在初始化之后要执行的方法
// 如果有切面,生成代理类也是在这个步骤处理
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
初始化完了之后,将BeanName从singletonsCurrentlyInCreation这个Set结构中删除,再将生成的Bean放入到第一级缓存singletonObjects当中,并且删除第二级和第三级缓存,这样B的实例就生成好了,B生成好了之后又回到A的populateBean方法就完成了A实例中的B的依赖注入
5.设置exposedObject
在B通过initializeBean方法完成初始化后返回的wrappedBean,如果有切面的话,其实返回的是代理对象,但是A对象的代理对象已经在B的实例化过程当中放到了earlySingletonObjects中,那么A在执行initializeBean方法时就不应该再去重新生成一个代理对象,而是应该从earlySingletonObjects中去取,然后直接赋值给exposedObject即可,这一步非常重要,不然会导致B中引用的A对象和singletonObjects中的A对象不是同一个对象,代码如下
代码语言:javascript复制public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
if (bean != null) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
if (this.earlyProxyReferences.remove(cacheKey) != bean) {
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;AnnotationAwareAspectJAutoProxyCreator
}
在initializeBean方法中的applyBeanPostProcessorsAfterInitialization方法中会调用AnnotationAwareAspectJAutoProxyCreator的父类AbstractAutoProxyCreator的postProcessAfterInitialization方法,在此方法中如果earlyProxyReferences中包含了该Bean,说明已经通过getEarlyBeanReference方法生成了代理类,这里就不会再执行wrapIfNecessary方法
文末尾记录一个常见的面试题,为什么Spring解决循环依赖是三级缓存,而不是二级缓存?
个人理解:二级缓存也能解决问题,但是要使用二级缓存解决循环依赖,意味着所有Bean在实例化后就要完成AOP代理(因为在Spring中如果有AOP,注入的都是代理对象)这样违背了Spring设计的原则,Spring在设计的时候就是使用AnnotationAwareAspectJAutoProxyCreator这个BeanPostProcessor在initializeBean的最后一步来完成AOP代理,而不是在实例化后就立马进行AOP代理,只有当确实有循环依赖时,才会提前生成代理对象