回顾之前的内容IOC初始化之准备工作(定位、加载、注册) ,说到在ApplicationContext
初始化时,会先去根据资源路径去定位、加载并且注册Bean信息到BeanFactory
中,但此过程并未实例化,在结尾也说了,在调用BeanFactory的getBean方法时Bean才会真正实例化。那么在ApplicationContext
中是什么时候去初始化Bean的呢?回顾一下refresh方法:
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// Tell the subclass to refresh the internal bean factory.
//告诉子类启动refreshBeanFactory()方法,Bean定义资源文件的载入从
//子类的refreshBeanFactory()方法启动
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
//略...
// Instantiate all remaining (non-lazy-init) singletons.
//初始化所有剩余的单例Bean
finishBeanFactoryInitialization(beanFactory);
//略...
}
由refresh方法可知,ApplicationContext
将在方法接近末尾的时候去初始化Bean,但不是初始化所有Bean,而是作用域为singleton单例的且配置lazy-init=false才会进行初始化Bean的操作。
//对配置了lazy-init属性的Bean进行预实例化处理
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
//略...
// Instantiate all remaining (non-lazy-init) singletons.
//对配置了lazy-init属性的单态模式Bean进行预实例化处理
beanFactory.preInstantiateSingletons();
}
注意这里初始化方法还是委托给了我们上一篇文章说的BeanFactory去做,而不是ApplicationContext
,对于很多操作Bean的场景大部分都是由DefaultListableBeanFactory
去做。
//对配置lazy-init属性单态Bean的预实例化
@Override
public void preInstantiateSingletons() throws BeansException {
// Iterate over a copy to allow for init methods which in turn register new bean definitions.
// While this may not be part of the regular factory bootstrap, it does otherwise work fine.
List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
// Trigger initialization of all non-lazy singleton beans...
//遍历所有的beanNames
for (String beanName : beanNames) {
//获取指定名称的Bean定义
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
//Bean不是抽象的,是单态模式的,且lazy-init属性配置为false
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
//如果指定名称的bean是创建容器的Bean
if (isFactoryBean(beanName)) {
//FACTORY_BEAN_PREFIX=”&”,当Bean名称前面加”&”符号
//时,获取的是产生容器对象本身,而不是容器产生的Bean.
//调用getBean方法,触发容器对Bean实例化和依赖注入过程
final FactoryBean<?> factory = (FactoryBean<?>) getBean(FACTORY_BEAN_PREFIX + beanName);
//标识是否需要预实例化
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方法,触发容器对Bean实例化和依赖注入过程
getBean(beanName);
}
}
else {
getBean(beanName);
}
}
}
//略...
}
可以看到,这里会遍历所有的Bean,如果是单例且lazy-init=false才会进行初始化,而真正初始化的工作将从getBean方法 中展开。
在BeanFactory继承体系结构中,可以看到AbstractBeanFactory
这个抽象类实现了BeanFactory接口,自然在这个抽象类中会实现getBean方法:
//获取IOC容器中指定名称的Bean
@Override
public Object getBean(String name) throws BeansException {
//doGetBean才是真正向IoC容器获取被管理Bean的过程
return doGetBean(name, null, null, false);
}
//真正实现向IOC容器获取Bean的功能,也是触发依赖注入功能的地方
protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
//根据指定的名称获取被管理Bean的名称,剥离指定名称中对容器的相关依赖
//如果指定的是别名,将别名转换为规范的Bean名称
final String beanName = transformedBeanName(name);
Object bean;
// Eagerly check singleton cache for manually registered singletons.
//先从缓存中取是否已经有被创建过的单态类型的Bean
//对于单例模式的Bean整个IOC容器中只创建一次,不需要重复创建
Object sharedInstance = getSingleton(beanName);
//IOC容器创建单例模式Bean实例对象
if (sharedInstance != null && args == null) {
if (logger.isDebugEnabled()) {
//如果指定名称的Bean在容器中已有单例模式的Bean被创建
//直接返回已经创建的Bean
if (isSingletonCurrentlyInCreation(beanName)) {
logger.debug("Returning eagerly cached instance of singleton bean '" + beanName +
"' that is not fully initialized yet - a consequence of a circular reference");
}
else {
logger.debug("Returning cached instance of singleton bean '" + beanName + "'");
}
}
//获取给定Bean的实例对象,主要是完成FactoryBean的相关处理
//注意:BeanFactory是管理容器中Bean的工厂,而FactoryBean是
//创建创建对象的工厂Bean,两者之间有区别
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
else {
// Fail if we're already creating this bean instance:
// We're assumably within a circular reference.
//缓存没有正在创建的单例模式Bean
//缓存中已经有已经创建的原型模式Bean
//但是由于循环引用的问题导致实例化对象失败
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
// Check if bean definition exists in this factory.
//对IOC容器中是否存在指定名称的BeanDefinition进行检查,首先检查是否
//能在当前的BeanFactory中获取的所需要的Bean,如果不能则委托当前容器
//的父级容器去查找,如果还是找不到则沿着容器的继承体系向父级容器查找
BeanFactory parentBeanFactory = getParentBeanFactory();
//当前容器的父级容器存在,且当前容器中不存在指定名称的Bean
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
// Not found -> check parent.
//解析指定Bean名称的原始名称
String nameToLookup = originalBeanName(name);
if (parentBeanFactory instanceof AbstractBeanFactory) {
return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
nameToLookup, requiredType, args, typeCheckOnly);
}
else if (args != null) {
// Delegation to parent with explicit args.
//委派父级容器根据指定名称和显式的参数查找
return (T) parentBeanFactory.getBean(nameToLookup, args);
}
else {
// No args -> delegate to standard getBean method.
//委派父级容器根据指定名称和类型查找
return parentBeanFactory.getBean(nameToLookup, requiredType);
}
}
//创建的Bean是否需要进行类型验证,一般不需要
if (!typeCheckOnly) {
//向容器标记指定的Bean已经被创建
markBeanAsCreated(beanName);
}
try {
//根据指定Bean名称获取其父级的Bean定义
//主要解决Bean继承时子类合并父类公共属性问题
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);
// Guarantee initialization of beans that the current bean depends on.
//获取当前Bean所有依赖Bean的名称
String[] dependsOn = mbd.getDependsOn();
//如果当前Bean有依赖Bean
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 + "'");
}
//递归调用getBean方法,获取当前Bean的依赖Bean
registerDependentBean(dep, beanName);
//把被依赖Bean注册给当前依赖的Bean
getBean(dep);
}
}
// Create bean instance.
//创建单例模式Bean的实例对象
if (mbd.isSingleton()) {
//这里使用了一个匿名内部类,创建Bean实例对象,并且注册给所依赖的对象
sharedInstance = getSingleton(beanName, () -> {
try {
//创建一个指定Bean实例对象,如果有父级继承,则合并子类和父类的定义
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
// Explicitly remove instance from singleton cache: It might have been put there
// eagerly by the creation process, to allow for circular reference resolution.
// Also remove any beans that received a temporary reference to the bean.
//显式地从容器单例模式Bean缓存中清除实例对象
destroySingleton(beanName);
throw ex;
}
});
//获取给定Bean的实例对象
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
//IOC容器创建原型模式Bean实例对象
else if (mbd.isPrototype()) {
// It's a prototype -> create a new instance.
//原型模式(Prototype)是每次都会创建一个新的对象
Object prototypeInstance = null;
try {
//回调beforePrototypeCreation方法,默认的功能是注册当前创建的原型对象
beforePrototypeCreation(beanName);
//创建指定Bean对象实例
prototypeInstance = createBean(beanName, mbd, args);
}
finally {
//回调afterPrototypeCreation方法,默认的功能告诉IOC容器指定Bean的原型对象不再创建
afterPrototypeCreation(beanName);
}
//获取给定Bean的实例对象
bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
}
//要创建的Bean既不是单例模式,也不是原型模式,则根据Bean定义资源中
//配置的生命周期范围,选择实例化Bean的合适方法,这种在Web应用程序中
//比较常用,如:request、session、application等生命周期
else {
String scopeName = mbd.getScope();
final Scope scope = this.scopes.get(scopeName);
//Bean定义资源中没有配置生命周期范围,则Bean定义不合法
if (scope == null) {
throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
}
try {
//这里又使用了一个匿名内部类,获取一个指定生命周期范围的实例
Object scopedInstance = scope.get(beanName, () -> {
beforePrototypeCreation(beanName);
try {
return createBean(beanName, mbd, args);
}
finally {
afterPrototypeCreation(beanName);
}
});
//获取给定Bean的实例对象
bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
}
catch (IllegalStateException ex) {
throw new BeanCreationException(beanName,
"Scope '" + scopeName + "' is not active for the current thread; consider " +
"defining a scoped proxy for this bean if you intend to refer to it from a singleton",
ex);
}
}
}
catch (BeansException ex) {
cleanupAfterBeanCreationFailure(beanName);
throw ex;
}
}
// Check if required type matches the type of the actual bean instance.
//对创建的Bean实例对象进行类型检查
if (requiredType != null && !requiredType.isInstance(bean)) {
try {
T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);
if (convertedBean == null) {
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
}
return convertedBean;
}
catch (TypeMismatchException ex) {
if (logger.isDebugEnabled()) {
logger.debug("Failed to convert bean '" + name + "' to required type '" +
ClassUtils.getQualifiedName(requiredType) + "'", ex);
}
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
}
}
return (T) bean;
}
在doGetBean方法中,其实做了很多事,这里一一解释:
ObjectFactory
是一个功能接口,里面有一个模板提供方法,getObject,调用方法返回实例,所以在外面调用getSingleton方法时使用匿名类方式将子类createBean方法赋给ObjectFactory
对象的getObject方法,便于在getSingleton方法中可以调用。这里是一个面向函数式编程思想 。这里多一层getSingleton方法是为了解决循环依赖问题 ,下面会详细解释。到这里我们应该要明白了,真正去创建Bean的方法是createBean:
//创建Bean实例对象
@Override
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
if (logger.isDebugEnabled()) {
logger.debug("Creating instance of bean '" + beanName + "'");
}
RootBeanDefinition mbdToUse = mbd;
// Make sure bean class is actually resolved at this point, and
// clone the bean definition in case of a dynamically resolved Class
// which cannot be stored in the shared merged bean definition.
//判断需要创建的Bean是否可以实例化,即是否可以通过当前的类加载器加载
Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
mbdToUse = new RootBeanDefinition(mbd);
mbdToUse.setBeanClass(resolvedClass);
}
//略...
try {
// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
//如果Bean配置了初始化前和初始化后的处理器,则试图返回一个需要创建Bean的代理对象
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean != null) {
return bean;
}
}
catch (Throwable ex) {
throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
"BeanPostProcessor before instantiation of bean failed", ex);
}
try {
//创建Bean的入口
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
if (logger.isDebugEnabled()) {
logger.debug("Finished creating instance of bean '" + beanName + "'");
}
return beanInstance;
}
//略...
}
这里也分步骤进行解读:
InstantiationAwareBeanPostProcessor
接口的方法postProcessBeforeInstantiation。举个例子AbstractAutoProxyCreator
这个类实现了BeanPostProcessor
这个接口来完成AOP代理,但它同时也实现了InstantiationAwareBeanPostProcessor
这个接口,这个接口的方法调用时间即为上述Bean实例化与依赖注入之前(doCreateBean 才真正进行Bean实例化与依赖注入)。如果关于BeanPostProcessor
的知识不懂的话,可以看看下一章我会讲到Spring的自定义扩展方式,然后下下章讲到AOP的时候也会详细讲解AbstractAutoProxyCreator
实现InstantiationAwareBeanPostProcessor
接口的真正作用,这里读者只要记住,InstantiationAwareBeanPostProcessor
的调用时机是在Bean实例化以前。InstantiationAwareBeanPostProcessor
的回调方法没有获取到Bean(自定义扩展的内容,说明没有进行自定义扩展),那么进入真正创建Bean的方法doCreateBean。//真正创建Bean的方法
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
throws BeanCreationException {
// Instantiate the bean.
//封装被创建的Bean对象
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
final Object bean = instanceWrapper.getWrappedInstance();
//获取实例化对象的类型
Class<?> beanType = instanceWrapper.getWrappedClass();
if (beanType != NullBean.class) {
mbd.resolvedTargetType = beanType;
}
// Allow post-processors to modify the merged bean definition.
//调用PostProcessor后置处理器
synchronized (mbd.postProcessingLock) {
if (!mbd.postProcessed) {
try {
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Post-processing of merged bean definition failed", ex);
}
mbd.postProcessed = true;
}
}
// Eagerly cache singletons to be able to resolve circular references
// even when triggered by lifecycle interfaces like BeanFactoryAware.
//向容器中缓存单例模式的Bean对象,以防循环引用
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
if (logger.isDebugEnabled()) {
logger.debug("Eagerly caching bean '" + beanName +
"' to allow for resolving potential circular references");
}
//这里是一个匿名内部类,为了防止循环引用,尽早持有对象的引用
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
// Initialize the bean instance.
//Bean对象的初始化,依赖注入在此触发
//这个exposedObject在初始化完成之后返回作为依赖注入完成后的Bean
Object exposedObject = bean;
try {
//将Bean实例对象封装,并且Bean定义中配置的属性值赋值给实例对象
populateBean(beanName, mbd, instanceWrapper);
//初始化Bean对象
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
catch (Throwable ex) {
if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
throw (BeanCreationException) ex;
}
else {
//抛异常..略...
}
}
if (earlySingletonExposure) {
//获取指定名称的已注册的单例模式Bean对象
Object earlySingletonReference = getSingleton(beanName, false);
if (earlySingletonReference != null) {
//根据名称获取的已注册的Bean和正在实例化的Bean是同一个
if (exposedObject == bean) {
//当前实例化的Bean初始化完成
exposedObject = earlySingletonReference;
}
//当前Bean依赖其他Bean,并且当发生循环引用时不允许新创建实例对象
else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
String[] dependentBeans = getDependentBeans(beanName);
Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
//获取当前Bean所依赖的其他Bean
for (String dependentBean : dependentBeans) {
//对依赖Bean进行类型检查
if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
actualDependentBeans.add(dependentBean);
}
}
//略...
}
}
}
// Register bean as disposable.
//注册完成依赖注入的Bean
try {
registerDisposableBeanIfNecessary(beanName, bean, mbd);
}
catch (BeanDefinitionValidationException ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
}
return exposedObject;
}
BeanWrapper
,此封装类存放Bean实例对象、Bean的Class类型等。createBeanInstance(beanName, mbd, args) 方法会实例化Bean,并且封装成BeanWrapper
返回。注意此时仅仅只是调用构造器实例化Bean而已。假设aBean中需要依赖bBean,而bBean中也需要依赖aBean,这时初始化aBean时,需要进行依赖注入,所以需要初始化bBean,而在bBean初始化时又需要依赖注入,此时需要一个aBean,这就造成了一个死锁,aBean在等待bBean初始化好,才能完成aBean的初始化,而bBean又在等待aBean初始化好,才能完成bBean的初始化,那么在Spring中是如何解决这种循环依赖问题的呢?
让我们回顾一下时序,我们先是调用了getBean方法,接着调用doGetBean方法真正去获取Bean,不知读者是否还记得,此时会先去调用getSingleton(beanName) 方法,尝试获取一个单例实例:
@Nullable
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
//尝试先从singletonObjects获取实例
Object singletonObject = this.singletonObjects获取实例.get(beanName);
//如果singletonObjects没有存放此Bean的实例的话,获取早期暴露的实例
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
synchronized (this.singletonObjects) {
//先尝试从早期暴露缓存earlySingletonObjects中获取
singletonObject = this.earlySingletonObjects.get(beanName);
//早期暴露的缓存没有的话,去早期暴露的Map中获取
if (singletonObject == null && allowEarlyReference) {
//singletonFactories此Map即为早期暴露的Map
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
//如果可以获取到早期暴露的对象的话
if (singletonFactory != null) {
//从此singletonFactory中获取Bean实例
singletonObject = singletonFactory.getObject();
//存放在早期暴露的缓存中,下次取只需要从earlySingletonObjects拿即可
this.earlySingletonObjects.put(beanName, singletonObject);
//由于已经存放在缓存中,singletonFactories继续存放没有意义,移除
this.singletonFactories.remove(beanName);
}
}
}
}
return singletonObject;
}
此时读者需要记住几个Map,关注接下来的方法它们的put时机和put的value到底是什么:
ObjectFactory
对象,此时依然是面向函数式编程 ,此接口只是一个功能暴露接口,也就是最终调用singletonFactory.getObject(); 的方法为关键,该方法获取早期Bean实例。接着回忆一下,在尝试调用getSingleton方法未获得对象时,会判断是否为单例,如果Bean为单例则会调用getSingleton(String beanName, ObjectFactory singletonFactory) 方法,注意此时的方法与上面的参数不一样,重载方法:
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
Assert.notNull(beanName, "Bean name must not be null");
//此过程需要进行同步处理
synchronized (this.singletonObjects) {
//依然先尝试从singletonObjects中获取
Object singletonObject = this.singletonObjects.get(beanName);
//获取不到的话
if (singletonObject == null) {
//如果此时单例Bean已经是在创建了,由于是单例的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!)");
}
if (logger.isDebugEnabled()) {
logger.debug("Creating shared instance of singleton bean '" + beanName + "'");
}
//此时就是上述提到的创建Bean的标识,在此标记此Bean已经正在创建
beforeSingletonCreation(beanName);
boolean newSingleton = false;
boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
if (recordSuppressedExceptions) {
this.suppressedExceptions = new LinkedHashSet<>();
}
try {
//面向函数编程,调用功能接口中的方法获取单例Bean,getObject方法的实现
//在调用getSingleton之前就已经使用匿名类的方式传入
singletonObject = singletonFactory.getObject();
newSingleton = true;
}
catch (IllegalStateException ex) {
// Has the singleton object implicitly appeared in the meantime ->
// if yes, proceed with it since the exception indicates that state.
singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
throw ex;
}
}
catch (BeanCreationException ex) {
if (recordSuppressedExceptions) {
for (Exception suppressedException : this.suppressedExceptions) {
ex.addRelatedCause(suppressedException);
}
}
throw ex;
}
finally {
if (recordSuppressedExceptions) {
this.suppressedExceptions = null;
}
//此时移除Bean创建的标识,表示此Bean不在创建时间了,已经创建完成
afterSingletonCreation(beanName);
}
if (newSingleton) {
//此时会将创建好了的Bean存入单例Map中
addSingleton(beanName, singletonObject);
}
}
return singletonObject;
}
}
protected void addSingleton(String beanName, Object singletonObject) {
//需要同步处理
synchronized (this.singletonObjects) {
//加入singletonObjects以供后续getBean时直接获取实例
this.singletonObjects.put(beanName, singletonObject);
//将早期暴露的实例移除,就算不移除这里也没有用了,因为根本不会有进入此Map的时机
this.singletonFactories.remove(beanName);
//这里就更不用说了,不会有进入此Map的时机
this.earlySingletonObjects.remove(beanName);
this.registeredSingletons.add(beanName);
}
}
由于此时已经将完整的Bean(实例化以及依赖注入完成)创建出来了,所以直接放入singletonObjects这个Map中,以供后续getBean时就可以直接取出。如果你还记得上面我让你记住的那几个Map的话,此时你应该可以有一个承上启下的感觉,singletonObjects是在初始化Bean完成时才会put实例 。
此时我们回到创建单例Bean中:
// Create bean instance.
//创建单例模式Bean的实例对象
if (mbd.isSingleton()) {
//这里使用了一个匿名内部类,创建Bean实例对象,并且注册给所依赖的对象
sharedInstance = getSingleton(beanName, () -> {
try {
//创建一个指定Bean实例对象,如果有父级继承,则合并子类和父类的定义
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
// Explicitly remove instance from singleton cache: It might have been put there
// eagerly by the creation process, to allow for circular reference resolution.
// Also remove any beans that received a temporary reference to the bean.
//显式地从容器单例模式Bean缓存中清除实例对象
destroySingleton(beanName);
throw ex;
}
});
//获取给定Bean的实例对象
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
这里可以看得出来,此时将子类实现的createBean方法传入getSingleton中以供后续getObject调用,也就是说,真正创建Bean的方法是createBean(在上面说初始化的时候也有提到,所以这里只是提一下经过了哪些方法,不贴代码详细描述),而createBean中判断了一下此Bean是否可以实例化,接着调用真正干事情的doCreateBean方法去初始化Bean,此时会先调用构造器实例化此Bean,注意此时仅仅是实例化一个Bean对象出来,Bean实例还未依赖注入,此时会调用这样一段代码:
//向容器中缓存单例模式的Bean对象,以防循环引用
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
if (logger.isDebugEnabled()) {
logger.debug("Eagerly caching bean '" + beanName +
"' to allow for resolving potential circular references");
}
//这里是一个匿名内部类,为了防止循环引用,尽早持有对象的引用
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
上面也有说过,这里会判断是否为单例,且允许循环依赖,才会进入addSingletonFactory方法:
protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {
Assert.notNull(singletonFactory, "Singleton factory must not be null");
//同步处理
synchronized (this.singletonObjects) {
//如果singletonObjects不存在该Bean才进行早期暴露
if (!this.singletonObjects.containsKey(beanName)) {
//会put一个功能接口对象到singletonFactories这个Map中
this.singletonFactories.put(beanName, singletonFactory);
this.earlySingletonObjects.remove(beanName);
this.registeredSingletons.add(beanName);
}
}
}
此方法我称为一个早期暴露实例的方法,注意此时这里可以通过getEarlyBeanReference方法获得此时Bean的引用(Bean仅仅是实例化),然后将该方法传给ObjectFactory
这个功能接口的getObject方法,此时只需要将ObjectFactory
这个具有获取早期Bean引用的方法的对象put进singletonFactories这个Map中,读到这里,聪明的读者应该已经知道了Spring到底是如何解决循环依赖问题的了。
心中需要有一个时序图,你将会看的更清晰:
getBean -> doGetBean -> 先去singletonObjects这个Map中查看是否已经有Bean实例,如果没有 -> 此Bean为单例的情况下,查看singletonFactories此Map是否有早期暴露的单例Bean引用 -> 如果有证明此时这个单例Bean在其他地方已经在创建了,此时只需要返回此引用作为Bean实例即可。
此时就来回顾一下上述的循环依赖问题:
当创建aBean
时,先去看看singletonObjects是否已经有实例,显然是没有,然后就会实例化此Bean,在这之后,依赖注入之前,将aBean
的引用存放在singletonFactories这个Map中,然后进行依赖注入,此时发现aBean
依赖bBean
,所以需要去初始化bBean
,依然是先看看singletonObjects是否有bBean
,显然也没有,然后就实例化bBean
,在bBean
依赖注入时,发现此Bean
依赖aBean
,所以又去初始化aBean
了,然后aBean
又去singletonObjects看是否存在实例,显然此时还是没有的,然后去singletonFactories这个Map查找的时候,发现存在一个Bean引用,所以获取该引用作为aBean
,将此引用注入到bBean
完成bBean
依赖注入的过程,bBean
初始化结束,然后回到aBean
依赖注入,初始化bBean
成功,将bBean
注入到aBean
,然后aBean
初始化也成功,没有循环依赖问题。
为什么早期暴露一个引用就可以解决循环依赖问题呢?
还是看这个例子,在bBean
中注入的aBean
依赖仅仅是一个aBean
实例化之后还未依赖注入(不完整的aBean
)引用,但当aBean
也初始化好了,bBean
中的aBean
(此时是完整的aBean)不也初始化好了吗?因为引用指向的对象都是同一个地址,这样bBean
就能提前初始化好,只有bBean
初始化好了aBean
才能初始化好,所以解决了循环依赖的问题。
但此时有一个问题,在上面介绍的所有的过程都是针对于单例Bean的,如果不是单例Bean根本都不会进行上述操作,如果是原型Bean循环依赖另一个原型Bean怎么办呢?目前我所知道的这个应该是解决不了的,在初始化的过程中就会报循环依赖的异常,所以要保证Bean为单例,才可以循环依赖。
FactoryBean是Spring定义的一个特殊的Bean,先来看看它定义了什么方法:
//工厂Bean,用于产生其他对象
public interface FactoryBean<T> {
//获取容器管理的对象实例
@Nullable
T getObject() throws Exception;
//获取Bean工厂创建的对象的类型
@Nullable
Class<?> getObjectType();
//Bean工厂创建的对象是否是单态模式,如果是单态模式,则整个容器中只有一个实例
//对象,每次请求都返回同一个实例对象
default boolean isSingleton() {
return true;
}
}
如果此Bean是FactoryBean,就必须实现FactoryBean接口。通过该接口可以看出FactoryBean的一些特性:
它是一个特殊的Bean,从名字就可以看出来,它是由Bean结尾的,意味着是一个Bean,但此Bean是工厂类型的Bean,什么意思呢?普通Bean只是IOC容器管理的真正代码中使用的对象,但工厂Bean不是我们要使用的对象,它负责生产真正的Bean,它是一个工厂,但它也是由工厂(BeanFactory)生产出来的,也就是说,FactroyBean是用来生产Bean而生的。
在BeanFactory
接口中,定义了一个静态变量:
//对FactoryBean的转义定义,因为如果使用bean的名字检索FactoryBean得到的对象是工厂生成的对象,
//如果需要得到工厂本身,需要转义
String FACTORY_BEAN_PREFIX = "&";
这个用处是用来区分要获取的是FactoryBean本身还是FactoryBean生产出来的Bean。假设有一个FactoryBean,BeanName=“demo”,你调用getBean方法希望获取到它的本身,你需要加一个符号:getBean("&demo"),此时你get到的对象会是FactoryBean本身,如果不加此符号,会获取此FactoryBean的方法getObject生产出来的Bean作为返回值。没听懂?看看下面就懂了。
回顾以上初始化Bean的过程,我们回到getBean之后的doGetBean这个一开始的起点方法中:
// Create bean instance.
//创建单例模式Bean的实例对象
if (mbd.isSingleton()) {
//这里使用了一个匿名内部类,创建Bean实例对象,并且注册给所依赖的对象
sharedInstance = getSingleton(beanName, () -> {
try {
//创建一个指定Bean实例对象,如果有父级继承,则合并子类和父类的定义
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
// Explicitly remove instance from singleton cache: It might have been put there
// eagerly by the creation process, to allow for circular reference resolution.
// Also remove any beans that received a temporary reference to the bean.
//显式地从容器单例模式Bean缓存中清除实例对象
destroySingleton(beanName);
throw ex;
}
});
//获取给定Bean的实例对象
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
这里举一个创建单例Bean过程的一段代码。我们上面介绍了createBean的流程,此时返回一个Bean是已经是实例化好了并且依赖注入完成,各种回调方法完成之后的一个Bean实例sharedInstance
,但是它没有真正的返回出去,而是又执行了一个方法getObjectForBeanInstance:
//获取给定Bean的实例对象,主要是完成FactoryBean的相关处理
protected Object getObjectForBeanInstance(
Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {
// Don't let calling code try to dereference the factory if the bean isn't a factory.
//容器已经得到了Bean实例对象,这个实例对象可能是一个普通的Bean,
//也可能是一个工厂Bean,如果是一个工厂Bean,则使用它创建一个Bean实例对象,
//如果调用本身就想获得一个容器的引用,则指定返回这个工厂Bean实例对象
//如果指定的名称是容器的解引用(dereference,即是对象本身而非内存地址),
//且Bean实例也不是创建Bean实例对象的工厂Bean
if (BeanFactoryUtils.isFactoryDereference(name) && !(beanInstance instanceof FactoryBean)) {
throw new BeanIsNotAFactoryException(transformedBeanName(name), beanInstance.getClass());
}
// Now we have the bean instance, which may be a normal bean or a FactoryBean.
// If it's a FactoryBean, we use it to create a bean instance, unless the
// caller actually wants a reference to the factory.
//如果Bean实例不是工厂Bean,或者指定名称是容器的解引用,
//调用者向获取对容器的引用,则直接返回当前的Bean实例
if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {
return beanInstance;
}
//处理指定名称不是容器的解引用,或者根据名称获取的Bean实例对象是一个工厂Bean
//使用工厂Bean创建一个Bean的实例对象
Object object = null;
if (mbd == null) {
//从Bean工厂缓存中获取给定名称的Bean实例对象
object = getCachedObjectForFactoryBean(beanName);
}
//让Bean工厂生产给定名称的Bean对象实例
if (object == null) {
// Return bean instance from factory.
FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
// Caches object obtained from FactoryBean if it is a singleton.
//如果从Bean工厂生产的Bean是单态模式的,则缓存
if (mbd == null && containsBeanDefinition(beanName)) {
//从容器中获取指定名称的Bean定义,如果继承基类,则合并基类相关属性
mbd = getMergedLocalBeanDefinition(beanName);
}
boolean synthetic = (mbd != null && mbd.isSynthetic());
//调用FactoryBeanRegistrySupport类的getObjectFromFactoryBean方法,
//实现工厂Bean生产Bean对象实例的过程
object = getObjectFromFactoryBean(factory, beanName, !synthetic);
}
return object;
}
也就是说,每一个Bean在初始化完成时,都会进入这个方法,这个方法会判断该Bean是否是FactoryBean,如果是的话,我们需要get的并不是这个FactoryBean,而是FactoryBean生产出来的Bean。
//Bean工厂生产Bean实例对象
protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {
//Bean工厂是单态模式,并且Bean工厂缓存中存在指定名称的Bean实例对象
if (factory.isSingleton() && containsSingleton(beanName)) {
//多线程同步,以防止数据不一致
synchronized (getSingletonMutex()) {
//直接从Bean工厂缓存中获取指定名称的Bean实例对象
Object object = this.factoryBeanObjectCache.get(beanName);
//Bean工厂缓存中没有指定名称的实例对象,则生产该实例对象
if (object == null) {
//调用Bean工厂的getObject方法生产指定Bean的实例对象
object = doGetObjectFromFactoryBean(factory, beanName);
// Only post-process and store if not put there already during getObject() call above
// (e.g. because of circular reference processing triggered by custom getBean calls)
Object alreadyThere = this.factoryBeanObjectCache.get(beanName);
if (alreadyThere != null) {
object = alreadyThere;
}
else {
if (shouldPostProcess) {
try {
object = postProcessObjectFromFactoryBean(object, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(beanName,
"Post-processing of FactoryBean's singleton object failed", ex);
}
}
//将生产的实例对象添加到Bean工厂缓存中
this.factoryBeanObjectCache.put(beanName, object);
}
}
return object;
}
}
//调用Bean工厂的getObject方法生产指定Bean的实例对象
else {
Object object = doGetObjectFromFactoryBean(factory, beanName);
if (shouldPostProcess) {
try {
object = postProcessObjectFromFactoryBean(object, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(beanName, "Post-processing of FactoryBean's object failed", ex);
}
}
return object;
}
}
以上两种可能性都调用了同一个方法doGetObjectFromFactoryBean:
//调用Bean工厂的getObject方法生产指定Bean的实例对象
private Object doGetObjectFromFactoryBean(final FactoryBean<?> factory, final String beanName)
throws BeanCreationException {
Object object;
//安全验证,略...
//调用BeanFactory接口实现类的创建对象方法
object = factory.getObject();
//略...
return object;
}
为了凸显出主线,我删减了一些支线代码,在这里可以看出来,最终调用的是FactoryBean的getObject方法,正是FactoryBean接口定义的这个方法,此方法为生产Bean的方法。
为了加深理解,我举一个生产环境都会用到的一个FactoryBean来演示到底FactoryBean有什么用。
这里我拿MyBatis与Spring整合包下的一个类MapperFactoryBean
作为例子讲解一下:
/**
* {@inheritDoc}
*/
@Override
public T getObject() throws Exception {
return getSqlSession().getMapper(this.mapperInterface);
}
/**
* {@inheritDoc}
*/
@Override
public boolean isSingleton() {
return true;
}
这里贴两个主要方法(需要有一点MyBatis的基础),我在分析MyBatis那篇文章中有提到,我们定义的那些Mapper接口,其实是SqlSession调用getMapper方法创建出来的,从以上getObject中可以看出,MapperFactoryBean
是一个专门生产Mapper的一个FactoryBean,从isSingleton方法中可以看出,获取的Mapper都为单例。我们回忆一下在使用SSM的时候,如果是一个一个Mapper去配置成Bean放在IOC容器中,需要这样写:
<bean id="demoMapper" class="org.mybatis.Spring.mapper.MapperFactoryBean">
<property name="mapperInterface" value="com.demo.DemoMapper">property>
<property name="sqlSessionFactory" ref="sqlSessionFactory">property>
bean>
请注意,此Bean的class类型就是我们上面介绍的MapperFactoryBean
,其中有属性mapperInterface ,根据此属性去使用getObject方法获取真正的Mapper对象,就算你直接配置一个Mapper扫描路径,它的底层也是将扫描到的每一个mapper接口类型作为MapperFactoryBean
,以一个FactoryBean的形式存放在IOC容器中,当getBean的时候其实是调用MapperFactoryBean
这个FactoryBean的getObject方法:
@Autowired
private DemoMapper demoMapper
也就是说,你这样使用一个Mapper的时候,Spring容器其实是先获取MapperFactoryBean
,然后调用所有Bean都会调用的方法getObjectForBeanInstance去进行判断,发现此Bean为一个FactoryBean,调用此Bean的getObject方法,也就是委派其中的SqlSession去getMapper,从而获取真正的Mapper。
到此就结束了初始化Bean的全过程,我们可以总结出来几件事:
BeanFactory
的)Map
中,这可以节省时间,一些单例Bean在启动时就已经创建好,使用时只需获取Map中实例即可。