《spring源码深度解析》第五章bean的加载
1.先分析一段spring中加载bean的一个方法.
protected <T> T doGetBean(String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly) throws BeansException {
//根据入参name获取对应的beanName String beanName = this.transformedBeanName(name);
//目的:1. 检查缓存中或者实例工厂中是否已经加载该bean
//创建单例bean的时候会存在依赖注入的情况,为避免循环依赖,spring创建bean的原则是不等bean创建完成就将创建bean的objectFactory提早曝光并加入缓存中
//当创建当前bean需要依赖上个bean的时候,直接使用objectFactory
//直接尝试从缓存或者singletonFactories中的ObjectFactory中获取bean
Object sharedInstance = this.getSingleton(beanName);
Object bean; //目标bean已创建
if(sharedInstance != null && args == null) { if(this.logger.isTraceEnabled()) {
//判断bean是否为单例,输出相应log if(this.isSingletonCurrentlyInCreation(beanName)) { this.logger.trace("Returning eagerly cached instance of singleton bean \'" + beanName + "\' that is not fully initialized yet - a consequence of a circular reference"); } else { this.logger.trace("Returning cached instance of singleton bean \'" + beanName + "\'"); } } //返回对应的实例,有时候存在如:BeanFactory的情况下,并不返回实例本身而是返回指定某一方法返回的实例 bean = this.getObjectForBeanInstance(sharedInstance, name, beanName, (RootBeanDefinition)null); } else {
//只有在单例的情况下才会尝试解决循环依赖,原型(prototype)模式的情况下,若存在循环依赖,直接抛出异常 if(this.isPrototypeCurrentlyInCreation(beanName)) { throw new BeanCurrentlyInCreationException(beanName); } //获取parentBeanFactory BeanFactory ex = this.getParentBeanFactory(); if(ex != null && !this.containsBeanDefinition(beanName)) { //若factory不为空且在已加载的bean缓存中(beanDefinationMap)不存在该beanName,尝试parentBeanFactory中寻找
String var28 = this.originalBeanName(name); if(ex instanceof AbstractBeanFactory) {
//递归循环在beanFactory中寻找 return ((AbstractBeanFactory)ex).doGetBean(var28, requiredType, args, typeCheckOnly); } if(args != null) { return ex.getBean(var28, args); } if(requiredType != null) { return ex.getBean(var28, requiredType); } return ex.getBean(var28); } //如果不只是做类型检查,此处做个标记进行记录 if(!typeCheckOnly) { this.markBeanAsCreated(beanName); } try {
//将存储XML配置文件的GenericBeanDefination转换为RootBeanDefination,若当前beanName存在父类的情况,则合并父类的相关属性 RootBeanDefinition ex1 = this.getMergedLocalBeanDefinition(beanName); this.checkMergedBeanDefinition(ex1, beanName, args); String[] dependsOn = ex1.getDependsOn(); String[] scopeName;
//若存在依赖,则递归实例化依赖的bean if(dependsOn != null) { scopeName = dependsOn; int scope = dependsOn.length; for(int ex2 = 0; ex2 < scope; ++ex2) { String dep = scopeName[ex2]; if(this.isDependent(beanName, dep)) { throw new BeanCreationException(ex1.getResourceDescription(), beanName, "Circular depends-on relationship between \'" + beanName + "\' and \'" + dep + "\'"); } //缓存依赖调用 this.registerDependentBean(dep, beanName); try { this.getBean(dep); } catch (NoSuchBeanDefinitionException var24) { throw new BeanCreationException(ex1.getResourceDescription(), beanName, "\'" + beanName + "\' depends on missing bean \'" + dep + "\'", var24); } } } //实例化依赖bean后便可以实例化mbd本身了&单例模式创建 if(ex1.isSingleton()) { sharedInstance = this.getSingleton(beanName, () -> { try { return this.createBean(beanName, ex1, args); } catch (BeansException var5) { this.destroySingleton(beanName); throw var5; } }); bean = this.getObjectForBeanInstance(sharedInstance, name, beanName, ex1); } else if(ex1.isPrototype()) {
//多例(prototype)模式下创建 scopeName = null; Object var29; try { this.beforePrototypeCreation(beanName); var29 = this.createBean(beanName, ex1, args); } finally { this.afterPrototypeCreation(beanName); } bean = this.getObjectForBeanInstance(var29, name, beanName, ex1); } else {
//既不是单例又不是多例的情况下,先获取当前bean的作用域 String var30 = ex1.getScope();
//若不是已规定的原型类型,则直接抛出异常 Scope var31 = (Scope)this.scopes.get(var30); if(var31 == null) { throw new IllegalStateException("No Scope registered for scope name \'" + var30 + "\'"); } try { Object var32 = var31.get(beanName, () -> { this.beforePrototypeCreation(beanName); Object var4; try { var4 = this.createBean(beanName, ex1, args); } finally { this.afterPrototypeCreation(beanName); } return var4; }); bean = this.getObjectForBeanInstance(var32, name, beanName, ex1); } catch (IllegalStateException var23) { throw new BeanCreationException(beanName, "Scope \'" + var30 + "\' 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", var23); } } } catch (BeansException var26) { this.cleanupAfterBeanCreationFailure(beanName); throw var26; } } //类型转换 if(requiredType != null && !requiredType.isInstance(bean)) { try { Object var27 = this.getTypeConverter().convertIfNecessary(bean, requiredType); if(var27 == null) { throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass()); } else { return var27; } } catch (TypeMismatchException var25) { if(this.logger.isTraceEnabled()) { this.logger.trace("Failed to convert bean \'" + name + "\' to required type \'" + ClassUtils.getQualifiedName(requiredType) + "\'", var25); } throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass()); } } else { return bean; } }
通过阅读上面代码,对于bean的加载过程中所涉及的步骤大致分下面几步:
1. 转换对应的beanName: a. 入参的beanName可能是别名而不是类名 b.可能是beanFactory.所以需要加以解析
解析内容包括:
a. 去除beanFactory的修饰符,即如果入参name="&aa",则去掉修饰符&,使得name=aa
b. 取指定的alias所表示的beanName.即bean的本名而非别名
2. 尝试从缓存中加载单例: 单例bean在spring中只会创建一次,后续再创建,直接从单例缓存中获取 . 若加载不成功,则再次尝试从singletonFactories中加载.
3. bean的实例化: 若从缓存中得到的bean是原始状态.则需要对bean进行实例化.
注:缓存中读取到的bean只是最原始的bean.并不一定是最终想要的. 例如实际项目中需对目标bean进行处理. 那就需要经过其他的方法处理后再次获得理想的实例bean .
4. 原型模式的依赖检查: 只有单例的情况下才会尝试解决循环依赖 . 因为单例模式下,一个容器中bean只会加载及实例化一次 . 当遇到循环依赖时 , 如A依赖B , 当实例化A时,先去加载B , 再实例化A.当加载
5. 检测parentFactory: 如果当前缓存中没有目标bean的话,就会去父类工厂中加载.
6.将存储XML的GenericBeanDefinition转换为RootBeanDefinition. 从XML中读取到的bean的信息都是存储在GenericBeanDefinition中的 , 而后续针对bean的所有的处理都是针对RootBeanDefinition的,所以加以转换 . 同时也合并父类bean的属性
7.寻找依赖bean
8. 针对不同的scope进行创建bean
9. 类型转换.将返回的bean转换成方法指定的requiretype.: 返回的bean其实是一个string,这里需转换为我们所需要的目标类型 .
注 : 缓存集合类 . 可翻看AbstractBeanFactory/DefaultSingletonBeanRegistry等源码中.
常见的一些集合类如 : singletonObjects[Map]:用于保存beanName和创建bean的实例之间的关系
singletonFactories[Map]:用于保存 BeanName和创建 bean的 factory之间的关系
registeredSingletons : 用来保存当前所有已注册的 bean
earlySingletonObjects[Map]: 也是保存beanName和 创建bean的factory之间的关系的 , 于singletonFactories区别是, 存储的是循环依赖的时候创建的bean .当单例bean放到里面后, 在bean的创建过程中,就可以通过getBean()获取到实例了 . 在bean加载完成后,即bean的实例加入singletonFactories中后 , 将从 earlySingletonObjects中移除 .
代码可参考 :
1 public void registerSingleton(String beanName, Object singletonObject) throws IllegalStateException { 2 Assert.notNull(beanName, "Bean name must not be null"); 3 Assert.notNull(singletonObject, "Singleton object must not be null"); 4 Map var3 = this.singletonObjects; 5 synchronized(this.singletonObjects) { 6 Object oldObject = this.singletonObjects.get(beanName); 7 if(oldObject != null) { 8 throw new IllegalStateException("Could not register object [" + singletonObject + "] under bean name \'" + beanName + "\': there is already object [" + oldObject + "] bound"); 9 } else { 10 this.addSingleton(beanName, singletonObject); 11 } 12 } 13 } 14 15 protected void addSingleton(String beanName, Object singletonObject) { 16 Map var3 = this.singletonObjects; 17 synchronized(this.singletonObjects) { 18 this.singletonObjects.put(beanName, singletonObject); 19 this.singletonFactories.remove(beanName); 20 this.earlySingletonObjects.remove(beanName); 21 this.registeredSingletons.add(beanName); 22 } 23 } 24 25 protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) { 26 Assert.notNull(singletonFactory, "Singleton factory must not be null"); 27 Map var3 = this.singletonObjects; 28 synchronized(this.singletonObjects) { 29 if(!this.singletonObjects.containsKey(beanName)) { 30 this.singletonFactories.put(beanName, singletonFactory); 31 this.earlySingletonObjects.remove(beanName); 32 this.registeredSingletons.add(beanName); 33 } 34 35 } 36 }
singletonsCurrentlyInCreation[Set]:用于加载实例前记录加载状态.
循环依赖 : 即A中依赖B . B中依赖A .
spring容器的循环依赖包括构造器循环依赖和setter循环依赖 .
构造器循环依赖 : 是无法解决的 . 遇到这种情况 , 只能抛出BeanCurrentlyInCreationException异常表示循环依赖 .
setter循环依赖 : 是通过spring容器提前暴露刚完成构造器注入但未完成其他步骤的bean来完成的 .
spring解决循环依赖的方案 : 只能解决单例模式下的setter循环依赖 .
提前暴露一个工厂方法 . 从而使得其他bean能从earlySingletonObjects缓存中引用到该bean . 完成bean的实例化 .
prototype范围的依赖处理: spring无法完成 . 因为spring容器本身不缓存该作用域的bean . 因此无法像单例bean那样提前暴露一个创建中的bean

浙公网安备 33010602011771号