Spring -Bean的加载

对于Bean的加载的功能,在Spring中的调用方式:
MyTestBean bean=(MyTestBean) bf.getBean(“MyTestBean”);
Spring中的代码实现;
在AbstractBeanFactory中getBean()方法:

 public Object getBean(String name) throws BeansException {
        return this.doGetBean(name, (Class)null, (Object[])null, false);
    }

protected  T doGetBean(final String name, @Nullable final Class requiredType,
			@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
       //提取对应的beanName
		final String beanName = transformedBeanName(name);
		Object bean;

		// Eagerly check singleton cache for manually registered singletons.
		/**
		 * 检查缓存或者实例工厂中是否有对应的实例
		 * 因为在创建单例Bean的时候,会存在依赖注入的情况,在创建依赖注入的时候为了避免循环依赖
		 * Spring创建bean的原则是不等bean创建完成就会将创建bean的ObjectFactory提早曝光
		 * 也就是将Object加入到缓存中,一旦下一个Bean要创建的时候需要依赖上一个bean直接使用
		 */
		//直接尝试从缓存中获取singletonFactoris中的ObjectFactory中获取
		Object sharedInstance = getSingleton(beanName);
		if (sharedInstance != null && args == null) {
			if (logger.isTraceEnabled()) {
				if (isSingletonCurrentlyInCreation(beanName)) {
					logger.trace("Returning eagerly cached instance of singleton bean '" + beanName +
							"' that is not fully initialized yet - a consequence of a circular reference");
				}
				else {
					logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
				}
			}
			//返回对应的实例,有时候在BeanFactory的情况并不是直接返回实例本身而是返回指定方法返回的实例
			bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
		}

		else {
			// Fail if we're already creating this bean instance:
			// We're assumably within a circular reference.
			//只有在单例的情况才会尝试解决循环依赖,原型模式情况下,如果存在
			//A中有B,B中有A,那么当依赖注入的时候,就会产生当A还没创建完成的时候,因为
			//对于B的创建再次返回创建A,造成循环依赖,
			//isPrototypeCurrentlyInCreation(bean)为true
			if (isPrototypeCurrentlyInCreation(beanName)) {
				throw new BeanCurrentlyInCreationException(beanName);
			}

			// Check if bean definition exists in this factory.
			//如果BeanDefinition中所有加载的类不包括beanName,则尝试从parentBeanFactory中检测
			BeanFactory parentBeanFactory = getParentBeanFactory();
			if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
				// Not found -> check parent.
				//在parent中寻找
				String nameToLookup = originalBeanName(name);
				if (parentBeanFactory instanceof AbstractBeanFactory) {
					return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
							nameToLookup, requiredType, args, typeCheckOnly);
				}
				//递归到BeanFactory中寻找
				else if (args != null) {
					// Delegation to parent with explicit args.
					return (T) parentBeanFactory.getBean(nameToLookup, args);
				}
				else if (requiredType != null) {
					// No args -> delegate to standard getBean method.
					return parentBeanFactory.getBean(nameToLookup, requiredType);
				}
				else {
					return (T) parentBeanFactory.getBean(nameToLookup);
				}
			}
            //如果不仅仅是做类型检查而是创建bean,这里要记录
			if (!typeCheckOnly) {
				markBeanAsCreated(beanName);
			}

			try {
				//将XML文件储存的GenericBeanDefinition转化为RootBeanDefinition。
				//如果指定的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();
				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);
						try {
							getBean(dep);
						}
						catch (NoSuchBeanDefinitionException ex) {
							throw new BeanCreationException(mbd.getResourceDescription(), beanName,
									"'" + beanName + "' depends on missing bean '" + dep + "'", ex);
						}
					}
				}

				// Create bean instance.
				//实例化依赖的bean后便可以创建mbf本身了
				if (mbd.isSingleton()) {
					//singleton模式的创建
					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.
							destroySingleton(beanName);
							throw ex;
						}
					});
					bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
				}
                //prototype模式的创建
				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 {
					//指定的scope上实例化bean
					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, () -> {
							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.
		//检查需要的类型是否符合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.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. 转换对应的beanNam
    传入的name不一定是beanName,也有可能是别名,或者FactoryBean。所以需要解析:
    1.去除掉FactoryBean的修饰符,eg:name=”&aa”,就会首先除去&使name=”aa”。
    2.取指定的alias所表示最终的beanName,例如A指向B的bean就返回B;
    若A指向别名B,B指向beanC,则返回C
  2. 尝试从缓存中加载单例:
    单例在Spring的同一个容器中只会创建一次,后续再获取Bean,就直接从单例的缓存中获取,这里只是尝试加载,首先尝试从缓存中加载,如果加载不成功,再次尝试从singletonFactories中加载,因为在创建单例bean的时候会存在依赖注入的情况,在创建bean的时候为了避免循环,在Spring中创建Bean的原则是不等bean创建完成就会创建bean的ObjectFactory提早曝光加入到缓存中,一旦下一个bean需要依赖上一个bean则直接使用ObjectFactory。
  3. bean的实例化
    如果从缓存中得到了bean的原始状态,则需要对bean进行实例化,缓存中记录的只是最原始的bean的状态,并不一定是最终想要的bean。假如我们需要对工厂bean进行处理,那么这里得到的只是工厂bean的初始状态,但是我们真正需要的是工厂bean中定义的Factory-method方法中返回的bean,而getObjectForBeanInstance就是完成这个工作的。
  4. 原型模式的依赖检测
    只有在单例情况下才会尝试解决循环依赖,如果存在A中有B的属性,B中有A的属性,那么当依赖注入的时候,就会产生当A还未创建完成的时候因为对于B创建再次返回创建A,造成循环依赖,也就是isPrototypeCurrentlyInCreation(beanName)判断true。
  5. 检测parentBeanFactory
    如果没有数据的话,直接转到父类工厂上去加载,parentBeanFactory != null && !containsBeanDefinition(beanName)。当parentBeanFactory为空时,就没有了后面的,!containsBeanDefinition(beanName)检测如果当前的XML配置文件中不包含beanName的对应的配置,就只能去parentBeanFactory尝试,然后递归调用getBean方法。
  6. 将存XML配置文件的GenericBeanDefinition转化为RootBeanDefinition
    在XML文件中读取到的bean的信息是存储在GenericBeanDefinition的,但是后续所有的bean的操作都是针对RootBeanDefinition的,所以需要转化,转化时,如果父类的bean不为空,则进行合并。
  7. 寻找依赖
    因为bean的初始化过程中可能会用到某些属性,某些属性很可能是动态配置的,并且配置成依赖其他的bean,那么这个时候就有必要先加载依赖的bean,所以在Spring的加载顺序中,在初始化某一个bean的时候,首先会初始化这个bean所对应的依赖。
  8. 针对不同的scope进行bean的创建
    在Spring中存在不同的scope,其中默认的是singleton,但是还有prototype、request、session之类的,在这个步骤之中,Spring会根据不同的配置进行不同的初始化的策略。
  9. 类型转化
    程序到了这里返回bean后已经基本结束了,通常对该方法的调用参数requiredType是空的,但是可能会存在其他情况,例如bean是个String,但是requiredType传入的Integer类型的,这个步骤就是将返回的bean转化成为requiredType所指定的类型。在Spring中提供了多种转化器,用户也可以自己扩展转化器。
    经过上面的9个步骤,bean的加载就结束了,这个时候就可以返回所需要的bean,上面最重要的步骤是步骤8,针对同的scope进行bean的创建。

你可能感兴趣的:(Java,Spring)