Spring IoC的细节--AbstractAutowireCapableBeanFactory.getObjectForBeanInstance(instan,name,beanName,bd)

AbstractBeanFactory.java:

	protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
			@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {

		// 转换bean的名称,由于传入的name有可能是获取FactoryBean的解引用(&+beanName,会去除&)
		// 假如是别名,则获取别名关联的beanName
		final String beanName = transformedBeanName(name);  //代码1
		Object bean;

		// 首先检查单例的缓存中是查找bean,也是为了防止多次创建单例模式的bean
		Object sharedInstance = getSingleton(beanName);  //代码2

		// 判断sharedInstance对象不为空,且args为空,原因是args仅用在创建新实例的时候使用,而非检索现有实例,方法注释写的
		if (sharedInstance != null && args == null) {
			...
			//获取Bean实例
			//情况1:普通bean,则返回直接普通bean实例
			//情况2:FactoryBean,分两种。一种是name里面带&,则返回FactoryBean本身,否则,返回由FactoryBean创建的实例
			bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);  //代码3
		}

		else {

			// 假如原型实例已创建,则报错,防止循环引用
			if (isPrototypeCurrentlyInCreation(beanName)) {
				throw new BeanCurrentlyInCreationException(beanName);
			}


			// 检查当前容器和父容器是否存在BeanDefinition
			BeanFactory parentBeanFactory = getParentBeanFactory();
			if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
				// 没有找到,则在父容器中查找
				String nameToLookup = originalBeanName(name);
				if (parentBeanFactory instanceof AbstractBeanFactory) {
					return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
							nameToLookup, requiredType, args, typeCheckOnly);
				}
				else if (args != null) {

					// 有明确的参数的时候委派给父容器获取bean
					// 此时会让父级容器根据指定名称和参数查找bean
					return (T) parentBeanFactory.getBean(nameToLookup, args);
				}
				else {

					// 没有参数的时候  委派给标准的getBean方法
					// 此时会让父级容器根据指定类型和名称查找bean
					return parentBeanFactory.getBean(nameToLookup, requiredType);
				}
			}

			// 创建的Bean是否需要进行类型验证,一般不需要
			if (!typeCheckOnly) {
				// 向容器标记指定的Bean已经被创建
				markBeanAsCreated(beanName);
			}

			try {
				// 获取Root级别的BeanDefinition
				final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
				checkMergedBeanDefinition(mbd, beanName, args);

				// 保证当前bean所依赖的bean的初始化
				// 意思是先初始化当前bean所依赖的bean,即调用getBean方法执行
				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 + "'");
						}
						// 注册依赖bean
						registerDependentBean(dep, beanName);
						// 递归getBean方法
						getBean(dep);
					}
				}

				// 完成依赖的配置后,以下代码开始创建实例

				// 单例
				if (mbd.isSingleton()) {
					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.
							destroySingleton(beanName);
							throw ex;
						}
					});
					//获取Bean实例
					bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
				}
				// 原型
				else if (mbd.isPrototype()) {
					// It's a prototype -> create a new instance.
					Object prototypeInstance = null;
					try {
						// 创建原型Bean前的回调方法调用
						beforePrototypeCreation(beanName);
						// 创建原型Bean
						prototypeInstance = createBean(beanName, mbd, args);
					}
					finally {
						// 创建原型Bean之后的回调方法调用
						afterPrototypeCreation(beanName);
					}
					//获取Bean实例
					bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
				}
				// 其他 例如Web应用程序中的request、session、application等生命周期
				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, () -> {
							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;
			}
		}

		// 检查对于返回值的类型是否有类型限制,有则转为对应类型的
		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的时候,多处代码调用到getObjectForBeanInstance方法,下面我们看看其具体实现:
AbstractAutowireCapableBeanFactory.java:

	protected Object getObjectForBeanInstance(
			Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {
		// 获取当前线程是否有正在创建的Bean,有的话,注册该依赖关系
		String currentlyCreatedBean = this.currentlyCreatedBean.get();
		if (currentlyCreatedBean != null) {
			registerDependentBean(beanName, currentlyCreatedBean);
		}

		return super.getObjectForBeanInstance(beanInstance, name, beanName, mbd);
	}

继续调用父类AbstractBeanFactory的getObjectForBeanInstance方法:

AbstractBeanFactory:

//获取Bean实例
	//情况1:普通bean,则返回直接普通bean实例
	//情况2:FactoryBean,分两种。一种是name里面带&,则返回FactoryBean本身,否则,返回由FactoryBean创建的实例
	protected Object getObjectForBeanInstance(
			Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {

		// 如果bean非工厂,别让调用代码尝试去做解引用
		if (BeanFactoryUtils.isFactoryDereference(name)) {
			if (beanInstance instanceof NullBean) {
				return beanInstance;
			}
			if (!(beanInstance instanceof FactoryBean)) {
				throw new BeanIsNotAFactoryException(transformedBeanName(name), beanInstance.getClass());
			}
		}


		//假如是普通bean实例(非FactoryBean),则直接返回
		//如果是FactoryBean,并且name中带有&,则表示调用者需要FactoryBean本身,则返回
		//假如是FactoryBean,并且name中不带&,则返回由FactoryBean创建的实例
		if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {
			return beanInstance;
		}

		Object object = null;
		if (mbd == null) {
			//从FactoryBean创建的实例缓存中获取
			object = getCachedObjectForFactoryBean(beanName);
		}
		if (object == null) {

			FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
			// Caches object obtained from FactoryBean if it is a singleton.
			if (mbd == null && containsBeanDefinition(beanName)) {
				mbd = getMergedLocalBeanDefinition(beanName);
			}
			boolean synthetic = (mbd != null && mbd.isSynthetic());

			//从FactoryBean获取实例对象
			object = getObjectFromFactoryBean(factory, beanName, !synthetic);
		}
		return object;
	}

上述代码,在执行类型和name的验证后,假如是普通bean对象,则直接返回,如果为FactoryBean,则会判断调用者是想使用FactoryBean本身,还是想通过FactoryBean来创建bean。假如name中带有&,则表示调用者想获取FactoryBean,则直接返回实例对象。如果没有带&,则使用FactoryBean开始创建bean实例。调用其父类FactoryBeanRegistrySupport的getObjectFromFactoryBean方法,下面看看其对应实现:

FactoryBeanRegistrySupport:

protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {

		//通过FactoryBean创建过的单例会缓存起来
		if (factory.isSingleton() && containsSingleton(beanName)) {
			//加锁,由于以下操作必须原子性,该处的全局锁由DefaultSingletonBeanRegistry
			//中的singletonObjects成员变量提供,其为一个ConcurrentHashMap对象
			synchronized (getSingletonMutex()) {
				//获取缓存单例,并返回,如果存在的话
				Object object = this.factoryBeanObjectCache.get(beanName);
				if (object == null) {
					//假设单例为空,则需要执行创建操作,创建操作其实就是调用factory.getObject方法
					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)
					//TODO 这里两次null的检查不知道具体有何作用,因为已经加了synchronized了
					//注释说的自定义调用getBean引起循环依赖会导致问题,但如果导致问题,通过二次检查非空,好像也不能根本解决。本人能力有限,该处代码不明白其作用,读者如果知晓的,请帮忙解答
					Object alreadyThere = this.factoryBeanObjectCache.get(beanName);
					if (alreadyThere != null) {
						object = alreadyThere;
					}
					else {
						if (shouldPostProcess) {
							try {
								isSingletonCurrentlyInCreation(beanName);
								//后置处理
								object = postProcessObjectFromFactoryBean(object, beanName);
							}
							catch (Throwable ex) {
								...
							}
						}
						//缓冲实例对象
						this.factoryBeanObjectCache.put(beanName, object);
					}
				}
				return object;
			}
		}
		else {
			//假如非单例对象,或者本容器没有该单例,则直接执行创建操作
			Object object = doGetObjectFromFactoryBean(factory, beanName);
			if (shouldPostProcess) {
				try {
					object = postProcessObjectFromFactoryBean(object, beanName);
				}
				catch (Throwable ex) {
					...
				}
			}
			return object;
		}
	}

上述代码其实主要是调用doGetObjectFromFactoryBean方法创建实例,其对应实现其实很简单,就是调用了FactoryBean接口的getObject方法实例化bean,并返回。不过对于单例对象,将会做缓存,保存在FactoryBeanRegistrySupport对象的成员变量factoryBeanObjectCache中。并在获取前做一次缓存检查。检查过程的两次判断非null,本人还不是很明白其原理。后续理解其原理后,会更新本文纠正。

//调用工厂的方法创建实例
	private Object doGetObjectFromFactoryBean(final FactoryBean<?> factory, final String beanName)
			throws BeanCreationException {

		Object object;
		try {
			//JDK安全性验证
			if (System.getSecurityManager() != null) {
				AccessControlContext acc = getAccessControlContext();
				try {
					object = AccessController.doPrivileged((PrivilegedExceptionAction<Object>) factory::getObject, acc);
				}
				catch (PrivilegedActionException pae) {
					throw pae.getException();
				}
			}
			else {
				//创建实例
				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) {
			if (isSingletonCurrentlyInCreation(beanName)) {
				throw new BeanCurrentlyInCreationException(
						beanName, "FactoryBean which is currently in creation returned null from getObject");
			}
			object = new NullBean();
		}
		return object;
	}

自此,FactoryBean创建bean的操作就讲述完毕了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值