【spring源码分析】IOC容器初始化(七)

时间:2022-09-30 11:33:09

前言:在【spring源码分析】IOC容器初始化(六)中分析了从单例缓存中加载bean对象,由于篇幅原因其核心函数

FactoryBeanRegistrySupport#getObjectFromFactoryBean并未进行详细分析,本文将继续对bean加载过程的分析。


FactoryBeanRegistrySupport#getObjectFromFactoryBean

 protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {
// 为单例模式,其缓存中存在该bean实例
if (factory.isSingleton() && containsSingleton(beanName)) {
/**
* 做同步,内部其实使用的就是{@link DefaultSingletonBeanRegistry#singletonObjects}
*/
synchronized (getSingletonMutex()) {
// 从缓存中获取指定的factoryBean
Object object = this.factoryBeanObjectCache.get(beanName);
if (object == null) {
// 为空,则从FactoryBean中获取对象
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)
// 再次从缓存中获取bean对象,主要是因为循环依赖
Object alreadyThere = this.factoryBeanObjectCache.get(beanName);
if (alreadyThere != null) {
object = alreadyThere;
} else {
// 需要后续处理
if (shouldPostProcess) {
// 如果该Bean处于创建中,则返回处理对象,而不是存储该对象
if (isSingletonCurrentlyInCreation(beanName)) {
// Temporarily return non-post-processed object, not storing it yet..
return object;
}
// 单例bean的前置处理 用于添加标志,当前bean正处于创建中
beforeSingletonCreation(beanName);
try {
// 对FactoryBean获取的对象进行后置处理,返回生成的对象
object = postProcessObjectFromFactoryBean(object, beanName);
} catch (Throwable ex) {
throw new BeanCreationException(beanName,
"Post-processing of FactoryBean's singleton object failed", ex);
} finally {
// 单例bean的后置处理 和前置处理相反,前置添加,后置移除 移除标志,当前bean不处于创建中
afterSingletonCreation(beanName);
}
}
// 添加到factoryBeanObjectCache中进行缓存
if (containsSingleton(beanName)) {
this.factoryBeanObjectCache.put(beanName, object);
}
}
}
return object;
}
} else {
// 不满足第一个条件,不是单例,或者缓存中不存在,则从FactoryBean中获取对象
Object object = doGetObjectFromFactoryBean(factory, beanName);
// 需要后续处理
if (shouldPostProcess) {
try {
// 对FactoryBean获取的对象进行后处理
// 返回生成的对象
object = postProcessObjectFromFactoryBean(object, beanName);
} catch (Throwable ex) {
throw new BeanCreationException(beanName, "Post-processing of FactoryBean's object failed", ex);
}
}
return object;
}
}

分析:

函数分两大分支:

#1.单例且singletonObjects缓存中存在(该分支为同步方法)

  • #1.1:FactoryBean为单例,并且缓存中存在该bean对象(containsSingleton方法其实就是判断singletonObjects集合中是否存在bean对象),首先从缓存中获取factoryBean对象object,如果object=null,则从doGetObjectFromFactoryBean方法中获取对象。注意:这里再次从factoryBeanObjectCache缓存中尝试获取对象(主要是循环依赖问题,有可能这时该bean对象已经加载了,就不用再次加载了),如果缓存中已存在bean对象,则使用缓存中对象,并直接返回。
  • #1.2:如果factoryBeanObjectCache缓存中不存在对象且需要后置处理,则首先判断该bean对象是否正在被创建,如果是,则直接返回,注意这里未进行缓存;然后对单例bean进行前置添加处理(beforeSingletonCreation)、后置处理(postProcessObjectFromFactoryBean)、后置移除标志处理(afterSingletonCreation)。
  • #1.3:最后将缓存生成的bean对象

#2.不满足(#1)中的任何一条件

  • 首先从doGetObjectFromFactoryBean方法中获取获取bean对象,如果需要后置处理,则调用postProcessObjectFromFactoryBean方法进行处理,最后返回生成过的bean对象。

在上述分析中涉及到几个函数,下面一一进行分析。

FactoryBeanRegistrySupport#doGetObjectFromFactoryBean

 private Object doGetObjectFromFactoryBean(final FactoryBean<?> factory, final String beanName)
throws BeanCreationException { Object object;
try {
// 如果权限不为空
if (System.getSecurityManager() != null) {
AccessControlContext acc = getAccessControlContext();
try {
// 从FactoryBean中获取Bean对象[factory::getObject] 其实与else分支一样的
object = AccessController.doPrivileged((PrivilegedExceptionAction<Object>) factory::getObject, acc);
} catch (PrivilegedActionException pae) {
throw pae.getException();
}
} else {
// 如果权限为空,则从Factory中获取Bean对象
object = factory.getObject();
}
} catch (FactoryBeanNotInitializedException ex) {
throw new BeanCurrentlyInCreationException(beanName, ex.toString());
} catch (Throwable ex) {
throw new BeanCreationException(beanName, "FactoryBean threw exception on object creation", ex);
} // 进行一波校验
// Do not accept a null value for a FactoryBean that's not fully
// initialized yet: Many FactoryBeans just return null then.
if (object == null) {
// 如果bean正在被创建,则抛出异常
if (isSingletonCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(
beanName, "FactoryBean which is currently in creation returned null from getObject");
}
object = new NullBean();
}
return object;
}

分析:

根据是否具有权限,通过FactoryBean#getObject获取bean对象,如果bean对象为null且正在被创建,则抛出异常,否则实例化一个NullBean对象进行返回。

DefaultSingletonBeanRegistry#isSingletonCurrentlyInCreation

     /**
* 正在创建中的单例 Bean 的名字的集合
* Names of beans that are currently in creation.
*/
private final Set<String> singletonsCurrentlyInCreation =
Collections.newSetFromMap(new ConcurrentHashMap<>(16)); public boolean isSingletonCurrentlyInCreation(String beanName) {
return this.singletonsCurrentlyInCreation.contains(beanName);
}

分析:

该函数判断bean是否正处于创建之中,该方法要与beforeSingletonCreation和afterSingletonCreation配合起来分析才能明白其重要性,他们记录了bean的加载状态,是检查当前bean是否处于创建中的关键处,对解决bean的循环依赖起着重要作用。

DefaultSingletonBeanRegistry#beforeSingletonCreation

     protected void beforeSingletonCreation(String beanName) {
// 这里会添加到正在创建bean的集合中
// 注意第一个条件,如果存在,则为false,直接短路
// 只有当第一个条件不存在[false]时,才会去进行添加操作
if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.add(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
}

分析:

注意这里就会将正在创建的beanName添加到singletonsCurrentlyInCreation集合中,第一个条件是判断该bean是否不会被检测。

DefaultSingletonBeanRegistry#afterSingletonCreation

 protected void afterSingletonCreation(String beanName) {
if (!this.inCreationCheckExclusions.contains(beanName)
&& !this.singletonsCurrentlyInCreation.remove(beanName)) { // 移除
// 如果移除失败,则抛出IllegalStateException异常
throw new IllegalStateException("Singleton '" + beanName + "' isn't currently in creation");
}
}

分析:

afterSingletonCreation方法与beforeSingletonCreation方法的功能相反,用于将beanName移除正在创建的集合singletonsCurrentlyInCreation,表明bean创建完成。

postProcessObjectFromFactoryBean

该方法的默认实现,就是返回当前bean对象。

 // FactoryBeanRegistrySupport
protected Object postProcessObjectFromFactoryBean(Object object, String beanName) throws BeansException {
return object;
}

当然,子类可以对该方法进行重写。

 // AbstractAutowireCapableBeanFactory

     protected Object postProcessObjectFromFactoryBean(Object object, String beanName) {
return applyBeanPostProcessorsAfterInitialization(object, beanName);
} public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
throws BeansException { Object result = existingBean;
// 遍历BeanPostProcessor
for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
// 进行处理
// TODO: 2019/4/2 具体处理过程需详细查看,这里先走大流程
Object current = beanProcessor.postProcessAfterInitialization(result, beanName);
// 返回为空,则返回传入的Object对象
if (current == null) {
return result;
}
// 修改result
result = current;
}
return result;
}

分析:

这里主要是遍历BeanPostProcessor,然后对bean对象进行处理,关于后置处理器的分析后面再做分析。

到这里从单例缓存中获取bean对象的相应源码已分析完成,接下来看单例缓存中无bean对象时,Spring的处理流程,再次将getBean的切入点代码贴出来。

 protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException { // .........省略从单例缓存中获取bean对象的代码
} else {
// Fail if we're already creating this bean instance:
// We're assumably within a circular reference.
// Spring只能解决单例模式下的循环依赖,在原型模式下如果存在循环依赖则抛出异常
// 这里检测原型模式下,该bean是否在加载,如果在加载则抛出异常
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
} // 如果当前容器中没有找到,则从父类容器中加载
// Check if bean definition exists in this factory.
BeanFactory parentBeanFactory = getParentBeanFactory();
/**
* 调用{@link DefaultListableBeanFactory#containsBeanDefinition(String)}方法
* 其实就是在beanDefinitionMap中判断是否存在beanName对应的BeanDefinition
*/
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
// Not found -> check parent.
// 确定原始的beanName
String nameToLookup = originalBeanName(name);
// 如果父类容器为AbstractBeanFactory,则委托父类处理
if (parentBeanFactory instanceof AbstractBeanFactory) {
return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
nameToLookup, requiredType, args, typeCheckOnly);
} else if (args != null) { // 用明确的args从parentBeanFactory中,获取Bean对象
// Delegation to parent with explicit args.
// 委托给父类构造函数getBean()处理
return (T) parentBeanFactory.getBean(nameToLookup, args);
} else if (requiredType != null) { // 用明确的requiredType从parentBeanFactory中,获取Bean对象
// No args -> delegate to standard getBean method.
// 没有args,委托给标准的getBean()处理
return parentBeanFactory.getBean(nameToLookup, requiredType);
} else {
// 直接使用nameToLookup从parentBeanFactory中获取Bean对象
return (T) parentBeanFactory.getBean(nameToLookup);
}
} // 如果不仅仅是做类型检查,而是创建bean,这里需要记录
if (!typeCheckOnly) {
markBeanAsCreated(beanName);
} try {
/**
* 从容器中获取beanName对应的GenericBeanDefinition对象,并转换成RootBeanDefinition对象
* GenericBeanDefinition的创建{@link BeanDefinitionReaderUtils#createBeanDefinition}方法
*/
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
// 检查合并的BeanDefinition
checkMergedBeanDefinition(mbd, beanName, args); // Guarantee initialization of beans that the current bean depends on.
// 处理所依赖的bean
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
for (String dep : dependsOn) {
// 若给定的依赖bean已经注册为依赖给定的bean
// 即循环依赖情况,抛出BeanCreationException异常
if (isDependent(beanName, dep)) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
}
// 缓存依赖调用
registerDependentBean(dep, beanName);
try {
// 递归处理依赖 Bean
getBean(dep);
} catch (NoSuchBeanDefinitionException ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"'" + beanName + "' depends on missing bean '" + dep + "'", ex);
}
}
}
// bean实例化
// Create bean instance.
// 单例模式
/**
* 这里有个已创建bean的重要方法createBean
* {@link AbstractAutowireCapableBeanFactory#createBean(String, RootBeanDefinition, Object[])}
*/
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, () -> {
try {
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 = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
} else if (mbd.isPrototype()) { // 原型模式
// It's a prototype -> create a new instance.
Object prototypeInstance = null;
try {
// 前置处理
beforePrototypeCreation(beanName);
/**
* 创建bean {@link AbstractAutowireCapableBeanFactory#createBean}
*/
prototypeInstance = createBean(beanName, mbd, args);
} finally {
/**
* 后置处理 与前置处理相反从{@link prototypesCurrentlyInCreation}中移除
*/
afterPrototypeCreation(beanName);
}
bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
} else { //其他作用域
// 获得scopeName对应的Scope对象
String scopeName = mbd.getScope();
final Scope scope = this.scopes.get(scopeName);
if (scope == null) {
throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
}
try {
/**
* 从指定的scope下创建bean
* {@link SimpleThreadScope#get方法}
*/
Object scopedInstance = scope.get(beanName, () -> {
beforePrototypeCreation(beanName);
try {
return createBean(beanName, mbd, args);
} finally {
afterPrototypeCreation(beanName);
}
});
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;
}
} // 检查需要的类型是否符合bean的实际类型
// Check if required type matches the type of the actual bean instance.
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.isTraceEnabled()) {
logger.trace("Failed to convert bean '" + name + "' to required type '" +
ClassUtils.getQualifiedName(requiredType) + "'", ex);
}
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
}
}
return (T) bean;
}

分析:

#1.首先通过AbstractBeanFactory#isPrototypeCurrentlyInCreation检查bean对象是否处于原型模式下的循环依赖,因为Spring只能解决单例模式下的循环依赖,如果在原型模式下也存在该bean对象,则会抛出异常。

 // AbstractBeanFactory
/**
* 原型模式下存储beanName的ThreadLocal<br/>
* Names of beans that are currently in creation.
*/
private final ThreadLocal<Object> prototypesCurrentlyInCreation =
new NamedThreadLocal<>("Prototype beans currently in creation");
protected boolean isPrototypeCurrentlyInCreation(String beanName) {
Object curVal = this.prototypesCurrentlyInCreation.get();
return (curVal != null &&
(curVal.equals(beanName) //相等
|| (curVal instanceof Set && ((Set<?>) curVal).contains(beanName)))); // 包含
}
  • 这里就是检查原型模式的ThreadLocal中是否已经存在对应的beanName。

#2.AbstractBeanFactory#getParentBeanFactory检查其父类BeanFactory是否存在,如果存在且beanDefinitionMap中不存在该BeanDefinition,则委托其父类通过getBean方法获取bean对象。注意这里首先会通过originalBeanName方法获取原始beanName。

 // AbstractBeanFactory
protected String originalBeanName(String name) {
String beanName = transformedBeanName(name);
if (name.startsWith(FACTORY_BEAN_PREFIX)) {
// 如果beanName以&开头,则在加上&进行返回 因为transformedBeanName中会去掉&
beanName = FACTORY_BEAN_PREFIX + beanName;
}
return beanName;
}
  • 首先通过transformedBeanName(该方法前面已经分析)获取真正的beanName,如果name以"&"开头,则将beanName加上"&"符号,因为transformedBeanName方法会去掉"&"符号。

#3.判断bean是否需要做类型检查,如果不仅仅做类型检查,则需要调用markBeanAsCreated函数进行记录。

 // AbstractBeanFactory
/**
* 已创建Bean的名字集合<br/>
* Names of beans that have already been created at least once.
*/
private final Set<String> alreadyCreated = Collections.newSetFromMap(new ConcurrentHashMap<>(256)); protected void markBeanAsCreated(String beanName) {
// 没有创建
if (!this.alreadyCreated.contains(beanName)) {
// 做同步
synchronized (this.mergedBeanDefinitions) {
// 再次进行检查,DoubleCheck模式
if (!this.alreadyCreated.contains(beanName)) {
// Let the bean definition get re-merged now that we're actually creating
// the bean... just in case some of its metadata changed in the meantime.
// 从mergedBeanDefinitions中删除beanName,并在下次访问时重新创建它
clearMergedBeanDefinition(beanName);
// 添加到已创建bean集合中
this.alreadyCreated.add(beanName);
}
}
}
}

#4. 接下来将对BeanDefinition进行转换,因为最开始创建的BeanDefinition类型为GenericBeanDefinition,getMergedLocalBeanDefinition方法在前面已经进行了分析,这里不在赘述。

#5.调用checkMergedBeanDefinition对转换后的RootBeanDefinition,如果RootBeanDefinition仍为抽象的,则抛出异常,这里抽象的对象还不能进行实例化。代码如下:

 // AbstractBeanFactory
protected void checkMergedBeanDefinition(RootBeanDefinition mbd, String beanName, @Nullable Object[] args)
throws BeanDefinitionStoreException { if (mbd.isAbstract()) {
throw new BeanIsAbstractException(beanName);
}
}

#6.处理依赖,如果在加载bean对象时,发现它有依赖bean的话,那么在初始化该bean的时候需要先初始化依赖的bean对象

 // 处理所依赖的bean
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
for (String dep : dependsOn) {
// 若给定的依赖bean已经注册为依赖给定的bean
// 即循环依赖情况,抛出BeanCreationException异常
if (isDependent(beanName, dep)) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
}
// 缓存依赖调用
registerDependentBean(dep, beanName);
try {
// 递归处理依赖 Bean
getBean(dep);
} catch (NoSuchBeanDefinitionException ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"'" + beanName + "' depends on missing bean '" + dep + "'", ex);
}
}
}

分析:

DefaultSingletonBeanRegistry#isDependent

 protected boolean isDependent(String beanName, String dependentBeanName) {
synchronized (this.dependentBeanMap) {
return isDependent(beanName, dependentBeanName, null);
}
}
private boolean isDependent(String beanName, String dependentBeanName, @Nullable Set<String> alreadySeen) {
// alreadySeen 已经检测的依赖bean
if (alreadySeen != null && alreadySeen.contains(beanName)) {
return false;
}
// 获取原始的beanName
String canonicalName = canonicalName(beanName);
// 获取当前beanName的依赖集合
Set<String> dependentBeans = this.dependentBeanMap.get(canonicalName);
// 不存在,则说明不存在注册依赖
if (dependentBeans == null) {
return false;
}
// 存在,则证明已经存在注册依赖
if (dependentBeans.contains(dependentBeanName)) {
return true;
}
// 递归检测依赖
for (String transitiveDependency : dependentBeans) {
if (alreadySeen == null) {
alreadySeen = new HashSet<>();
}
// 添加到alreadySeen
alreadySeen.add(beanName);
// 递推
if (isDependent(transitiveDependency, dependentBeanName, alreadySeen)) {
return true;
}
}
return false;
}

分析:

这里通过一些列判断,是否依赖的bean是否已经注入,如果注入则返回true,否则返回false。

#7.如果依赖检测通过,则调用registerDependentBean对依赖bean进行注入。

 // DefaultSingletonBeanRegistry

     /**
* 保存的是依赖beanName 映射关系:beanName --> 依赖beanName的集合<br/>
* Map between dependent bean names: bean name to Set of dependent bean names.
*/
private final Map<String, Set<String>> dependentBeanMap = new ConcurrentHashMap<>(64); /**
* 保存的是依赖 beanName 之间的映射关系:依赖 beanName - > beanName 的集合
* Map between depending bean names: bean name to Set of bean names for the bean's dependencies.
*/
private final Map<String, Set<String>> dependenciesForBeanMap = new ConcurrentHashMap<>(64); public void registerDependentBean(String beanName, String dependentBeanName) {
// 获取beanName
String canonicalName = canonicalName(beanName); // 做同步 添加<canonicalName,<dependentBeanName>>到dependentBeanMap中
synchronized (this.dependentBeanMap) {
Set<String> dependentBeans =
this.dependentBeanMap.computeIfAbsent(canonicalName, k -> new LinkedHashSet<>(8));
if (!dependentBeans.add(dependentBeanName)) {
return;
}
}
// 做同步 添加<canonicalName,<dependentBeanName>>到dependenciesForBeanMap中
synchronized (this.dependenciesForBeanMap) {
Set<String> dependenciesForBean =
this.dependenciesForBeanMap.computeIfAbsent(dependentBeanName, k -> new LinkedHashSet<>(8));
dependenciesForBean.add(canonicalName);
}
}

分析:

这里就是就是将依赖的beanName关系添加到dependentBeanMap、dependenciesForBeanMap集合中。

#8.最后通过getBean方法实例化依赖bean对象,该方法会在后面进行分析。

各种scope的Bean创建

在经过单例缓存中获取bean对象、从父类工厂中获取bean对象、处理依赖bean这三步后,接下来来到对各种scope的bean的创建。首先是单例模式bean对象的创建,我们知道singleton为Spring的bean的默认作用域,当然除了singleton之外,还有prototype、request等其他的scope。

#1.singleton的初始化代码如下

 // AbstractBeanFactory

 if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, () -> {
try {
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 = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}

分析:

单例模式bean的初始化是从getSingleton方法开始,当然这里还有一个重要的createBean方法,该方法我们留在后面进行分析,首先来看getSingleton方法。

 // DefaultSingletonBeanRegistry

 public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
Assert.notNull(beanName, "Bean name must not be null");
// 做同步
synchronized (this.singletonObjects) {
// 从缓存中检查一遍
// 因为singlton模式其实已经复用了创建的bean,所以该步骤必须检查
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 (logger.isDebugEnabled()) {
logger.debug("Creating shared instance of singleton bean '" + beanName + "'");
}
// 加载前置处理 其实就是打一个标记
beforeSingletonCreation(beanName);
// 首先将新的newSingleton设置为false
boolean newSingleton = false;
boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
if (recordSuppressedExceptions) {
this.suppressedExceptions = new LinkedHashSet<>();
}
try {
// 初始化bean
// 该过程其实是调用createBean()方法 这里是一个回调方法
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;
}
// 一堆异常处理后,进行后置处理 移除标志
afterSingletonCreation(beanName);
}
// 新的bean 加入缓存中
if (newSingleton) {
addSingleton(beanName, singletonObject);
}
}
return singletonObject;
}
}

分析(该方法同样为同步方法):

该方法其实并未真正创建bean对象,获取bean对象的核心点在于singletonObject = singletonFactory.getObject(),但该方法是由createBean回调产生的。这里仅仅是做了一部分准备和预处理步骤:

  • 再次从缓存中检查bean是否已经加载过,如果缓存中存在则直接返回。
  • beforeSingletonCreation前面已经分析过,记录加载单例bean的状态,表示正在被加载。
  • 然后调用singletonFactory.getObject方法实例化bean对象
  • afterSingletonCreation前面也分析过了,移除bean正在被加载的标志。
  • 将生成的bean对象加入缓存。

DefaultSingletonBeanRegistry#addSingleton

     /**
* Cache of singleton objects: bean name to bean instance.
* 存放的是单例 bean 的映射。
* <p>
* 对应关系为 bean name --> bean instance
*/
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256); /**
* Cache of singleton factories: bean name to ObjectFactory.<br/>
* 存放的是 ObjectFactory,可以理解为创建单例 bean 的 factory 。
* <p>
* 对应关系是 bean name --> ObjectFactory
*/
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16); /**
* Cache of early singleton objects: bean name to bean instance.<br/>
* 存放的是早期的 bean,对应关系也是 bean name --> bean instance。
* <p>
* 它与 {@link #singletonFactories} 区别在于 earlySingletonObjects 中存放的 bean 不一定是完整。
* <p>
* 从 {@link #getSingleton(String)} 方法中,我们可以了解,bean 在创建过程中就已经加入到 earlySingletonObjects 中了。
* 所以当在 bean 的创建过程中,就可以通过 getBean() 方法获取。
* <p>
* 这个 Map 也是【循环依赖】的关键所在。
*/
private final Map<String, Object> earlySingletonObjects = new HashMap<>(16); /**
* 存储已经注册的单例 进行缓存<br/>
* Set of registered singletons, containing the bean names in registration order.
*/
private final Set<String> registeredSingletons = new LinkedHashSet<>(256); protected void addSingleton(String beanName, Object singletonObject) {
synchronized (this.singletonObjects) {
this.singletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
this.earlySingletonObjects.remove(beanName);
this.registeredSingletons.add(beanName);
}
}

分析:

一个put、两个remove、一个add。

  • 由于已经实例化了bean,因此需要将单例bean进行缓存,singletonObjects.put。
  • 同理单例BeanFactory和提前曝光的bean也需要移除,singletonFactories.remove和earlySingletonObjects.remove。
  • registeredSingletons.add,已实例化的bean需要进行注册。

#2.原型模式

 if (mbd.isPrototype()) { // 原型模式
// It's a prototype -> create a new instance.
Object prototypeInstance = null;
try {
// 前置处理
beforePrototypeCreation(beanName);
/**
* 创建bean {@link AbstractAutowireCapableBeanFactory#createBean}
*/
prototypeInstance = createBean(beanName, mbd, args);
} finally {
/**
* 后置处理 与前置处理相反从{@link prototypesCurrentlyInCreation}中移除
*/
afterPrototypeCreation(beanName);
}
bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
}

分析:

原型模式下bean的初始化很简单,直接创建一个新Bean实例就可以了。

  • beforePrototypeCreation:记录加载原型模式bean的加载状态,前置处理。
  • createBean创建实例对象,该方法非常重要,后续会详细进行分析。
  • afterPrototypeCreation:移除创建时添加的标志,后置处理与beforePrototypeCreation方法功能相反。
  • 最后调用getObjectForBeanInstance获取实例,该方法在【spring源码分析】IOC容器初始化(六)中已经分析,这里不再赘述。

AbstractBeanFactory#beforePrototypeCreation

 1    /**
* 原型模式下存储beanName的ThreadLocal<br/>
* Names of beans that are currently in creation.
*/
private final ThreadLocal<Object> prototypesCurrentlyInCreation =
new NamedThreadLocal<>("Prototype beans currently in creation"); protected void beforePrototypeCreation(String beanName) {
// 从ThreadLocal中取出对象
Object curVal = this.prototypesCurrentlyInCreation.get();
if (curVal == null) {
// 如果为空,则设置值
this.prototypesCurrentlyInCreation.set(beanName);
} else if (curVal instanceof String) {
// 如果curVal为String类型,则进行添加
Set<String> beanNameSet = new HashSet<>(2);
beanNameSet.add((String) curVal);
beanNameSet.add(beanName);
this.prototypesCurrentlyInCreation.set(beanNameSet);
} else {
// 否则将curVal转换成set集合,添加beanName
Set<String> beanNameSet = (Set<String>) curVal;
beanNameSet.add(beanName);
}
}

分析:

这里的前置处理就是将beanName加入ThreadLocal中,逻辑简单。

AbstractBeanFactory#afterPrototypeCreation

     protected void afterPrototypeCreation(String beanName) {
Object curVal = this.prototypesCurrentlyInCreation.get();
if (curVal instanceof String) {
this.prototypesCurrentlyInCreation.remove();
} else if (curVal instanceof Set) {
Set<String> beanNameSet = (Set<String>) curVal;
beanNameSet.remove(beanName);
if (beanNameSet.isEmpty()) {
this.prototypesCurrentlyInCreation.remove();
}
}
}

分析:

后置处理与前置处理beforePrototypeCreation正好相反,将标记从ThreadLocal中移除。

#3.其他作用域

 // 获得scopeName对应的Scope对象
String scopeName = mbd.getScope();
final Scope scope = this.scopes.get(scopeName);
if (scope == null) {
throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
}
try {
/**
* 从指定的scope下创建bean
* {@link SimpleThreadScope#get方法}
*/
Object scopedInstance = scope.get(beanName, () -> {
beforePrototypeCreation(beanName);
try {
return createBean(beanName, mbd, args);
} finally {
afterPrototypeCreation(beanName);
}
});
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;
}

分析:

其他作用域bean的创建过程与原型模式的流程一样,只是获取bean的方式变成了Scope#get(String name,ObjectFactory<?> objectFactory)。

 //  SimpleThreadScope
public Object get(String name, ObjectFactory<?> objectFactory) {
// 获取scope缓存
Map<String, Object> scope = this.threadScope.get();
Object scopedObject = scope.get(name);
if (scopedObject == null) {
// 这里getObject也是进行方法回调
scopedObject = objectFactory.getObject();
// 加入缓存
scope.put(name, scopedObject);
}
return scopedObject;
}

这里仅仅是Scope接口的一种实现,该接口还有其他多种实现,其具体源码可查看相应实现类:

【spring源码分析】IOC容器初始化(七)

至此,Bean加载的大致流程已分析完毕,当然本篇文章并未分析一个很重要的函数createBean,该函数留在后续的文章继续分析。


by Shawn Chen,2019.04.22,下午。

【spring源码分析】IOC容器初始化(七)的更多相关文章

  1. SPRING源码分析&colon;IOC容器

    在Spring中,最基本的IOC容器接口是BeanFactory - 这个接口为具体的IOC容器的实现作了最基本的功能规定 - 不管怎么着,作为IOC容器,这些接口你必须要满足应用程序的最基本要求: ...

  2. Spring源码解析-ioc容器的设计

    Spring源码解析-ioc容器的设计 1 IoC容器系列的设计:BeanFactory和ApplicatioContext 在Spring容器中,主要分为两个主要的容器系列,一个是实现BeanFac ...

  3. spring源码分析---IOC&lpar;1&rpar;

    我们都知道spring有2个最重要的概念,IOC(控制反转)和AOP(依赖注入).今天我就分享一下spring源码的IOC. IOC的定义:直观的来说,就是由spring来负责控制对象的生命周期和对象 ...

  4. spring 源码之 ioc 容器的初始化和注入简图

    IoC最核心就是两个过程:IoC容器初始化和IoC依赖注入,下面通过简单的图示来表述其中的关键过程:

  5. Spring源码阅读-IoC容器解析

    目录 Spring IoC容器 ApplicationContext设计解析 BeanFactory ListableBeanFactory HierarchicalBeanFactory Messa ...

  6. Spring 源码剖析IOC容器(一)概览

    目录 一.容器概述 二.核心类源码解读 三.模拟容器获取Bean ======================= 一.容器概述 spring IOC控制反转,又称为DI依赖注入:大体是先初始化bean ...

  7. Spring源码解析-IOC容器的实现

    1.IOC容器是什么? IOC(Inversion of Control)控制反转:本来是由应用程序管理的对象之间的依赖关系,现在交给了容器管理,这就叫控制反转,即交给了IOC容器,Spring的IO ...

  8. Spring源码解析-IOC容器的实现-ApplicationContext

    上面我们已经知道了IOC的建立的基本步骤了,我们就可以用编码的方式和IOC容器进行建立过程了.其实Spring已经为我们提供了很多实现,想必上面的简单扩展,如XMLBeanFacroty等.我们一般是 ...

  9. Spring源码之IOC容器创建、BeanDefinition加载和注册和IOC容器依赖注入

    总结 在SpringApplication#createApplicationContext()执行时创建IOC容器,默认DefaultListableBeanFactory 在AbstractApp ...

随机推荐

  1. Entity Framework 6 Recipes 2nd Edition(12-3)译 -&gt&semi; 数据库连接日志

    12-3. 数据库连接日志 问题 你想为每次与数据库的连接和断开记录日志 解决方案 EF为DbContext的连接公开了一个StateChange 事件.我们需要处理这个事件, 为每次与数据库的连接和 ...

  2. eclipse安装genymotion插件。

    先发个我自己压缩的genymotion和VirtualBox,下载链接:http://pan.baidu.com/s/1o7wgJiU 1.在安装genymotion之后,打开eclipse,如下图操 ...

  3. &lbrack;deviceone开发&rsqb;-do&lowbar;Socket组件示例

    一.简介 do_Socket只实现了socket的客户端的功能,这个示例完整了展示了组件的基本用法,需要和sockettest3工具配合使用,sockettest3做为一个socket server来 ...

  4. 2013nanjignB

    B - Poor Warehouse Keeper Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & ...

  5. mysql 索引长度限制

    MyISAM存储引擎引键的长度综合不能超过1000字节 InnoDB单列索引长度不能超过767bytes,联合索引还有一个限制是3072

  6. &lbrack;C语言 - 1&period;2&rsqb; 类型说明符、字符、数组

    A.类型说明符(只能修饰int) short int: = short 2字节 long int: long 8字节 = long   输出占位符 %ld signed int: = signed 默 ...

  7. docker私服

    1.下载私服镜像docker pull registry 2.启动容器docker run -d -p 5000:5000 -v /opt/data/registry:/var/lib/registr ...

  8. web安全色

    web安全色产生的原因 不同的平台(Mac.PC等)有不同的调色板,不同的浏览器也有自己的调色板.这就意味着对于一幅图,显示在Mac上的Web浏览器中的图像,与它在PC上相同浏览器中显示的效果可能差别 ...

  9. python模块--zipfile文件压缩

    zipfile模块是python中一个处理压缩文件的模块,解决了不少我们平常需要处理压缩文件的需求 ,本文主要谈谈zipfile几个常用的用法. 首先我在Windows操作系统中创建如下的文件目录: ...

  10. BUAAOO第一单元的总结

    ---恢复内容开始--- Homework1 简单多项式求导 程序架构 由于对java的生疏和不了解,第一次作业很羞愧的只用了一个类. 1.在输入之后调用Polyformat函数检查输入的格式,A检索 ...