一般来说,Spring框架启动流程大体上分成两个大的步骤:IoC容器初始化和Bean的依赖注入。
Bean的依赖注入
Bean的依赖注入大致可分为如下过程:
转换对应beanName;
尝试从缓存中加载单例;
获取单例
创建Bean
转换对应beanName
考虑到传入的beanName可能是别名,也有可能是FactoryBean,因此需要进行必要的转换。简单来说,如果是FactoryBean的话,去除前面的修饰符“&”;如果是alias,取指定alias所表示的最终beanName。
尝试从缓存中加载单例
Spring框架中尝试加载单例的代码如下:
public Object getSingleton(String beanName) {
return this.getSingleton(beanName, true);
}
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null && this.isSingletonCurrentlyInCreation(beanName)) {
Map var4 = this.singletonObjects;
synchronized(this.singletonObjects) {
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null && allowEarlyReference) {
ObjectFactory<?> singletonFactory = (ObjectFactory)this.singletonFactories.get(beanName);
if (singletonFactory != null) {
singletonObject = singletonFactory.getObject();
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
}
}
}
}
- 代码中涉及到三个map类型的对象:singletonObjects、earlySingletonObjects、singletonFactories;
- 从代码逻辑中可以看到,首先尝试从singletonObjects中加载;
- 如果获取不到,再从earlySingletonObjects中获取;
- 如果再获取不到,则尝试从singletonFactories里面获取beanName对应得ObjectFactory;
- 然后调用这个ObjectFactory的getObject方法来创建bean,并放到earlySingletonObjects里面去;
- 然后从singletonFactories删除对应的ObjectFactory。
在得到bean的实例后需要调用getObjectForBeanInstance方法来检测一下正确性,其实就是检测当前bean是否为FactoryBean类型的bean,如果是,需要调用对应的getObject方法作为返回值。
protected Object getObjectForBeanInstance(Object beanInstance, String name, String beanName, RootBeanDefinition mbd) {
if (BeanFactoryUtils.isFactoryDereference(name) && !(beanInstance instanceof FactoryBean)) {
throw new BeanIsNotAFactoryException(this.transformedBeanName(name), beanInstance.getClass());
} else if (beanInstance instanceof FactoryBean && !BeanFactoryUtils.isFactoryDereference(name)) {
Object object = null;
if (mbd == null) {
object = this.getCachedObjectForFactoryBean(beanName);
}
if (object == null) {
FactoryBean<?> factory = (FactoryBean)beanInstance;
if (mbd == null && this.containsBeanDefinition(beanName)) {
mbd = this.getMergedLocalBeanDefinition(beanName);
}
boolean synthetic = mbd != null && mbd.isSynthetic();
object = this.getObjectFromFactoryBean(factory, beanName, !synthetic);
}
return object;
} else {
return beanInstance;
}
}
上述代码中对于非FactoryBean不做任何处理,而将从Factory中解析bean的工作委托给了getObjectFromFactoryBean方法。
protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {
if (factory.isSingleton() && this.containsSingleton(beanName)) {
synchronized(this.getSingletonMutex()) {
Object object = this.factoryBeanObjectCache.get(beanName);
if (object == null) {
object = this.doGetObjectFromFactoryBean(factory, beanName);
Object alreadyThere = this.factoryBeanObjectCache.get(beanName);
if (alreadyThere != null) {
object = alreadyThere;
} else {
if (object != null && shouldPostProcess) {
try {
object = this.postProcessObjectFromFactoryBean(object, beanName);
} catch (Throwable var9) {
throw new BeanCreationException(beanName, "Post-processing of FactoryBean's singleton object failed", var9);
}
}
this.factoryBeanObjectCache.put(beanName, object != null ? object : NULL_OBJECT);
}
}
return object != NULL_OBJECT ? object : null;
}
} else {
Object object = this.doGetObjectFromFactoryBean(factory, beanName);
if (object != null && shouldPostProcess) {
try {
object = this.postProcessObjectFromFactoryBean(object, beanName);
} catch (Throwable var11) {
throw new BeanCreationException(beanName, "Post-processing of FactoryBean's object failed", var11);
}
}
return object;
}
}
代码中只有一处需要注意的,那就是如果bean是单例的,那就要保证全局唯一,也因为是单例,可以不必重复创建,使用缓存来提高性能。最后去调用doGetObjectFromFactoryBean方法。
private Object doGetObjectFromFactoryBean(final FactoryBean<?> factory, String beanName) throws BeanCreationException {
Object object;
try {
if (System.getSecurityManager() != null) {
AccessControlContext acc = this.getAccessControlContext();
try {
object = AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
public Object run() throws Exception {
return factory.getObject();
}
}, acc);
} catch (PrivilegedActionException var6) {
throw var6.getException();
}
} else {
object = factory.getObject();
}
} catch (FactoryBeanNotInitializedException var7) {
throw new BeanCurrentlyInCreationException(beanName, var7.toString());
} catch (Throwable var8) {
throw new BeanCreationException(beanName, "FactoryBean threw exception on object creation", var8);
}
if (object == null && this.isSingletonCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName, "FactoryBean which is currently in creation returned null from getObject");
} else {
return object;
}
}
可以看到,通过直接调用getObject方法获取bean,并通过postProcessObjectFromFactoryBean方法完成相应的后处理。Spring获取bean的规则中有一条:尽可能保证所有bean初始化后都会调用注册的BeanPostProcessor的postProcessAfterInitialization方法进行处理。
获取单例
如果当前缓存中不存在对应的单例Bean,那就必须从头开始加载Bean,ObjectFactory的核心部分就是调用createBean方法。
sharedInstance = this.getSingleton(beanName, new ObjectFactory() {
public Object getObject() throws BeansException {
try {
return AbstractBeanFactory.this.createBean(beanName, mbd, args);
} catch (BeansException var2) {
AbstractBeanFactory.this.destroySingleton(beanName);
throw var2;
}
}
});
protected Object createBean(String beanName, RootBeanDefinition mbd, Object[] args) throws BeanCreationException {
if (this.logger.isDebugEnabled()) {
this.logger.debug("Creating instance of bean '" + beanName + "'");
}
this.resolveBeanClass(mbd, beanName, new Class[0]);
try {
mbd.prepareMethodOverrides();
} catch (BeanDefinitionValidationException var5) {
throw new BeanDefinitionStoreException(mbd.getResourceDescription(), beanName, "Validation of method overrides failed", var5);
}
Object beanInstance;
try {
beanInstance = this.resolveBeforeInstantiation(beanName, mbd);
if (beanInstance != null) {
return beanInstance;
}
} catch (Throwable var6) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName, "BeanPostProcessor before instantiation of bean failed", var6);
}
beanInstance = this.doCreateBean(beanName, mbd, args);
if (this.logger.isDebugEnabled()) {
this.logger.debug("Finished creating instance of bean '" + beanName + "'");
}
return beanInstance;
}
在调用doCreateBean方法之前,先调用了prepareMethodOverrides和resolveBeforeInstantiation两个方法,前者完成override属性处理,后者完成bean实例化的前置处理,此处暂不叙述,读者可关注后续文章。
创建Bean
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, Object[] args) {
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
//如果是单例则需要首先清除缓存
instanceWrapper = (BeanWrapper)this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
//根据指定bean使用对应的策略创建新的实例
instanceWrapper = this.createBeanInstance(beanName, mbd, args);
}
final Object bean = instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null;
Class<?> beanType = instanceWrapper != null ? instanceWrapper.getWrappedClass() : null;
Object var7 = mbd.postProcessingLock;
synchronized(mbd.postProcessingLock) {
if (!mbd.postProcessed) {
this.applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
mbd.postProcessed = true;
}
}
//如果是单例并且允许循环依赖并且当前bean正在创建中检测到循环依赖,则需要提早曝光
boolean earlySingletonExposure = mbd.isSingleton() && this.allowCircularReferences && this.isSingletonCurrentlyInCreation(beanName);
if (earlySingletonExposure) {
if (this.logger.isDebugEnabled()) {
this.logger.debug("Eagerly caching bean '" + beanName + "' to allow for resolving potential circular references");
}
this.addSingletonFactory(beanName, new ObjectFactory<Object>() {
public Object getObject() throws BeansException {
return AbstractAutowireCapableBeanFactory.this.getEarlyBeanReference(beanName, mbd, bean);
}
});
}
Object exposedObject = bean;
try {
//填充bean,注入属性值,如果存在依赖其他bean的属性,递归初始化所依赖的bean
this.populateBean(beanName, mbd, instanceWrapper);
if (exposedObject != null) {
exposedObject = this.initializeBean(beanName, exposedObject, mbd);
}
} catch (Throwable var17) {
if (var17 instanceof BeanCreationException && beanName.equals(((BeanCreationException)var17).getBeanName())) {
throw (BeanCreationException)var17;
}
throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Initialization of bean failed", var17);
}
if (earlySingletonExposure) {
Object earlySingletonReference = this.getSingleton(beanName, false);
if (earlySingletonReference != null) {
if (exposedObject == bean) {
exposedObject = earlySingletonReference;
} else if (!this.allowRawInjectionDespiteWrapping && this.hasDependentBean(beanName)) {
String[] dependentBeans = this.getDependentBeans(beanName);
Set<String> actualDependentBeans = new LinkedHashSet(dependentBeans.length);
String[] arr$ = dependentBeans;
int len$ = dependentBeans.length;
for(int i$ = 0; i$ < len$; ++i$) {
String dependentBean = arr$[i$];
if (!this.removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
actualDependentBeans.add(dependentBean);
}
}
if (!actualDependentBeans.isEmpty()) {
throw new BeanCurrentlyInCreationException(beanName, "Bean with name '" + beanName + "' has been injected into other beans [" + StringUtils.collectionToCommaDelimitedString(actualDependentBeans) + "] in its raw version as part of a circular reference, but has eventually been " + "wrapped. This means that said other beans do not use the final version of the " + "bean. This is often the result of over-eager type matching - consider using " + "'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");
}
}
}
}
try {
//根据scope注册bean
this.registerDisposableBeanIfNecessary(beanName, bean, mbd);
return exposedObject;
} catch (BeanDefinitionValidationException var16) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Invalid destruction signature", var16);
}
}
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, Object[] args) {
Class<?> beanClass = this.resolveBeanClass(mbd, beanName, new Class[0]);
if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Bean class isn't public, and non-public access not allowed: " + beanClass.getName());
} else if (mbd.getFactoryMethodName() != null) {
//如果工厂方法不为空则使用工厂方法初始化策略
return this.instantiateUsingFactoryMethod(beanName, mbd, args);
} else {
boolean resolved = false;
boolean autowireNecessary = false;
if (args == null) {
Object var7 = mbd.constructorArgumentLock;
synchronized(mbd.constructorArgumentLock) {
//根据参数确定调用的构造方法或者工厂方法
if (mbd.resolvedConstructorOrFactoryMethod != null) {
resolved = true;
autowireNecessary = mbd.constructorArgumentsResolved;
}
}
}
if (resolved) {
//确定使用构造方法自动注入还是使用默认构造方法构造
return autowireNecessary ? this.autowireConstructor(beanName, mbd, (Constructor[])null, (Object[])null) : this.instantiateBean(beanName, mbd);
} else {
Constructor<?>[] ctors = this.determineConstructorsFromBeanPostProcessors(beanClass, beanName);
//确定使用构造方法自动注入还是使用默认构造方法构造
return ctors == null && mbd.getResolvedAutowireMode() != 3 && !mbd.hasConstructorArgumentValues() && ObjectUtils.isEmpty(args) ? this.instantiateBean(beanName, mbd) : this.autowireConstructor(beanName, mbd, ctors, args);
}
}
}
从代码中可以看出,Spring通过autowireConstructor和instantiateBean两个方法创建Bean实例。前者逻辑复杂,代码量巨大,但从其功能实现的角度考虑了如下几个方面:
构造函数参数的确定(隐式参数、缓存、配置文件);
构造函数的确定;
根据确定的构造函数转换对应的参数类型;
构造函数不确定性的验证;
根据实例化策略以及得到的构造函数寄构造函数参数实例化Bean。
后者逻辑简单,由于不需要考虑参数,因此直接调用实例化策略进行实例化就可以了。实例化操作结束后,需要注入属性。重点是
autowireByName和autowireByType两个方法。
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 i$ = this.getBeanPostProcessors().iterator();
while(i$.hasNext()) {
BeanPostProcessor bp = (BeanPostProcessor)i$.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 i$ = this.getBeanPostProcessors().iterator();
while(i$.hasNext()) {
BeanPostProcessor bp = (BeanPostProcessor)i$.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);
}
}
}
此时Spring已经完成了bean的实例化和属性的填充,接着便会调用用户设定的初始化方法。一般而言,用户可以有三种途径自定义初始化方法,后续文章会有详细叙述,敬请关注。
总结
笔者花了两篇博文的篇幅大致介绍了Spring容器的启动过程,还有很多细节方面并未涉及,例如循环依赖、具体属性值注入等。平时开发时对于容器启动时打印的日志信息毫无感觉,现在读者可以结合博文再去关注日志信息,相信会有更深的体会。祝好!