Spring中Bean加载的过程是一个关键的步骤。这个过程主要是通过BeanFactoyr中的getBean方法来实现的。具体的方法是在AbstractBeanFactory方法中实现的。getBean方法主要有两个功能,首先是去缓存中读取bean,如果没有就实例化这个bean,实例化bean的过程是一个将GenericBeanDefinition转变为一个正式的bean的过程。
具体实现的方法是:
protected <T> T doGetBean(final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
Spring代码中有个特点是所有的具体执行的代码都是以do
开头。
protected <T> T doGetBean(
final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
throws BeansException {
final String beanName = transformedBeanName(name);
Object bean;
// Eagerly check singleton cache for manually registered singletons.
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
if (logger.isDebugEnabled()) {
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 = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
else {
// Fail if we're already creating this bean instance:
// We're assumably within a circular reference.
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
// Check if bean definition exists in this factory.
BeanFactory parentBeanFactory = getParentBeanFactory();
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
// Not found -> check parent.
String nameToLookup = originalBeanName(name);
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);
}
}
if (!typeCheckOnly) {
markBeanAsCreated(beanName);
}
try {
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);
// Guarantee initialization of beans that the current bean depends on.
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);
getBean(dep);
}
}
// Create bean instance.
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
@Override
public Object getObject() throws BeansException {
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.
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);
prototypeInstance = createBean(beanName, mbd, args);
}
finally {
afterPrototypeCreation(beanName);
}
bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
}
else {
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 {
Object scopedInstance = scope.get(beanName, new ObjectFactory<Object>() {
@Override
public Object getObject() throws BeansException {
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;
}
}
// Check if required type matches the type of the actual bean instance.
if (requiredType != null && bean != null && !requiredType.isAssignableFrom(bean.getClass())) {
try {
return getTypeConverter().convertIfNecessary(bean, requiredType);
}
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;
}
以上这段代码就是Spring中bean加载的过程。
第一步:
将beanName转变为正在的beanName原因是Spring中的aliasName的特性。Spring中内部维护了一个aliasBeanName和beanName之间的映射。
第二步:
先从singletonCache中获取到对应的bean。这个方法是DefaultSingletonBeanRegistry.getSingleton(String beanName)
中实现的。
这个过程可以做一个简单的介绍:
1.从存放完全生成了的单例对象的singletonObjects中获取完全生成的bean。
2.如果为空判断当前的bean是否正在创建。主要是通过判断singletonBeanInCreation是否包含了这个beanName
3.如果正在创建,那么从earlySingletonObjects中获取到对应的Object。(这个Object是一个被创建,但是还没有被赋值的。可以理解为一个对象的引用
4.如果Obejct的应用还没有创建,如果允许循环依赖,就从singletonFactorys中获取到ObjectFactory中的对象。ObjectFactory可以认为是一个工厂方法,主要主要用来实例化bean。
5.如果ObejctFactory不为空,这个时候从ObjectFactory中获取到对象,先将对象添加到earlySingletonObjects中,同时将对应的ObjectFactory从SingletonFactorys中移除。这个过程完成了ObjectFactory向earlySingletonBean的转变。
Spring中bean实例化的过程主要是这样几个过程:
RootBeanDefinition --> ObjectFactory --> earlySingeltonBean --> Obeject
为什么会有这么复杂执行过程主要是为了解决Spring中循环依赖解决方法小结。
第三步:如果获取了bean成功,这个时候需要判断一下这个实例是普通的Object还是一个FactoryBean。然后根据具体的情况获取到想要的bean。FactoryBean是如何实现的请见FactoyrBean小结
前面如果都失败了,说明这个bean对象并没有被缓存,就需要实例化bean了。
第四步:判断当前bean是否是一个prototype类型的,如果是就用AbstractBeanFactory中prototypesCurrentlyInCreation判断是否有循环依赖。主要是prototypesCurrentlyInCreation中记录了当前线程中正在创建的beanName信息,如果在创建当前bean的时候发现之前已经有一个相同的bean也在创建,这个时候就会有循环依赖的问题了。直接报错。
第五步:调用父BeanFactory中的getBean方法。这个过程和JVM中ClassLoader中双亲委派是一样的。
第六步:标记开始创建
具体实现的步骤如下:
1.将mergedBeanDefinitions中对应的RootBeanDefinition删除.
2.将当前bean添加到alreadyCreated 表示正在创建
这里有了一个doublecheck来保证线程安全。
第七步:
根据当前beanName获取到对应的GenericBeanDefinition,同时将这个对象转变为一个RootBeanDefinition对象,同时判断当前的RootBeanDefiniton是否是一个抽象类,如果是就抛异常。具体Spring中如何处理基础类的请看Spring中基础bean实现小结
第八步:
获取当前bean对应的depend的信息,如果出现循环依赖,那么就抛出异常。具体请看Spring中是如何处理循环dependOn的
以下就开始十里荷花对象:
第九步骤:判断如果是一个单例对象
就调用DefaultSingletonBeanRegistry.getSingleton(String beanName, ObjectFactory<?> singletonFactory)
方法来实例化当前的单例对象了。
其中ObjectFactory中getObject方法是调用了createBean(String beanName, RootBeanDefinition mbd, Object[] args)方法来实例化对象。
其中 createBean(String beanName, RootBeanDefinition mbd, Object[] args)
方法是当前系统中的关键。
具体如何创建的请看Spring中单例对象的创建小结
第十步:判断当前对象是一个prototype类型
创建一个单例prototype类型的对象。Spring创建prototype类型bean小结
第十一步:如果是其他类型的bean。调用对应类型的构造器。Spring中是如何创建其他Scope对象小结
第十四步:
将当前的object转变为想要的类型的对象。具体请看Spring中类型转变小结
总结:
Spring中doGetBean(final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
简单描述首先从缓存中获取到对应的对象,如果就根据不同的scope实例化bean。