八、Spring 源码解析之 bean 的加载流程三: bean 的实例化

  在六、Spring 源码解析之 bean 的加载过程介绍中我们介绍了bean 的加载的大致流程,其中第一步已经在该文中说过,这里来说第三步:bean 的实例化
  在 getBean() 方法中,getObjectForBeanInstance() 是个高频率使用的方法,无论是从缓存中获取 bean 还是根据不同的 scope 策略加载 bean。总之,我们得到 bean 的实例后要做的第一步就是调用这个方法来检测一下正确性,其实就是用于检测当前 bean 是否是 FactoryBean 类型的 bean ,如果是,那么需要调用该 bean 对应的 FactoryBean 实例中的 getObject() 作为返回值。
  无论是从缓存中获取到的 bean 还是通过不同的 scope 策略加载的 bean 都只是最原始的 bean 状态,并不一定是我们最终想要的 bean。举个栗子,假如我们需要对工厂 bean 进行处理,那么这里得到的其实是工厂 bean 的初始状态,但是我们真正需要的是工厂 bean 中定义的 factory-methods 方法返回的 bean,而 getObjectForBeanInstance() 方法就是完成这个工作的。

  • AbstractBeanFactory#doGetBean(final String name, @Nullable final Class requiredType,@Nullable final Object[] args, boolean typeCheckOnly)
    • AbstractBeanFactory#getObjectForBeanInstance(Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd)
      • FactoryBeanRegistrySupport#getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess)
        • FactoryBeanRegistrySupport#doGetObjectFromFactoryBean(final FactoryBean<?> factory, final String beanName)
        • AbstractAutowireCapableBeanFactory#postProcessObjectFromFactoryBean(Object object, String beanName)
	protected Object getObjectForBeanInstance(
			Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {

		// Don't let calling code try to dereference the factory if the bean isn't a factory.
		//如果指定的 name 是工厂相关(以 & 为前缀)
		if (BeanFactoryUtils.isFactoryDereference(name)) {
			if (beanInstance instanceof NullBean) {
				return beanInstance;
			}
			//如果指定的 name 是工厂相关(以 & 为前缀)但是 beanInstance 又不是 FactoryBean 类型则验证不通过
			if (!(beanInstance instanceof FactoryBean)) {
				throw new BeanIsNotAFactoryException(beanName, beanInstance.getClass());
			}
		}

		// Now we have the bean instance, which may be a normal bean or a FactoryBean.
		// If it's a FactoryBean, we use it to create a bean instance, unless the
		// caller actually wants a reference to the factory.
		/*
		 * 现在我们有了 beanInstance 这个实例,这个实例有可能是正常的 bean 或者是 FactoryBean:
		 *   若不是 FactoryBean ,那么就是正常的 bean 实例,直接返回即可
		 *   若是 FactoryBean,且传入的 name 加上了 & 前缀,那么说明客户端想获取工厂实例而不是工厂的 getObject() 方法返回
		 * 的实例,直接返回即可
		 */
		if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {
			return beanInstance;
		}

		/*
		 *     加载 FactoryBean(条件:若是 FactoryBean 且传入的 name 没有加上 & 前缀,说明希望调用 Factory#getObject()
		 * 返回 bean 实例)
		 */
		Object object = null;
		if (mbd == null) {
			//尝试从缓存中加载 bean
			object = getCachedObjectForFactoryBean(beanName);
		}
		if (object == null) {
			// Return bean instance from factory.
			//到这里已经明确知道 beanInstance 一定是 FactoryBean 类型
			FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
			// Caches object obtained from FactoryBean if it is a singleton.
			//containsBeanDefinition() 方法检测 BeanDefinitionMap 中也就是在所有已经加载的类中检测是否定义 beanName
			if (mbd == null && containsBeanDefinition(beanName)) {
				/*
				 *     将存储 XML 配置文件的 GenericBeanDefinition 转换为 RootBeanDefinition,如果指定 beanName 是子 bean
				 * 的话同时会合并父类的相关属性
				 */
				mbd = getMergedLocalBeanDefinition(beanName);
			}
			//是否使用户定义的而不是应用程序本身定义的
			boolean synthetic = (mbd != null && mbd.isSynthetic());
			object = getObjectFromFactoryBean(factory, beanName, !synthetic);
		}
		return object;
	}

  上面代码来看,真正核心代码委托给了 FactoryBeanRegistrySupport#getObjectFromFactoryBean() 方法。 getObjectForBeanInstance() 方法主要做了如下工作:
1.对 FactoryBean 正确性的验证。
2.对非 FactoryBean 不做任何处理。
3.对 bean 进行转换
4.将从 Factory 中解析 bean 的工作委托给 FactoryBeanRegistrySupport#getObjectFromFactoryBean()

	/**
	 * 方法功能:
	 *     返回的 bean 若是单例的,那就必须要保证全局唯一性,同时,也因为是单例的,所以不必重复创建,可以使用缓存来提高
	 * 性能,也就是说已经加载过就要记录下来以便于下次复用,否则的话就直接获取
	 */
	protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {
		// 若是单例
		if (factory.isSingleton() && containsSingleton(beanName)) {
			synchronized (getSingletonMutex()) {
				Object object = this.factoryBeanObjectCache.get(beanName);
				if (object == null) {
					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)
					Object alreadyThere = this.factoryBeanObjectCache.get(beanName);
					if (alreadyThere != null) {
						object = alreadyThere;
					} else {
						if (shouldPostProcess) {
							if (isSingletonCurrentlyInCreation(beanName)) {
								// Temporarily return non-post-processed object, not storing it yet..
								return object;
							}
							// 检查
							beforeSingletonCreation(beanName);
							try {
								object = postProcessObjectFromFactoryBean(object, beanName);
							}
							catch (Throwable ex) {
								throw new BeanCreationException(beanName,
										"Post-processing of FactoryBean's singleton object failed", ex);
							}
							finally {
								// 再次检查
								afterSingletonCreation(beanName);
							}
						}
						if (containsSingleton(beanName)) {
							this.factoryBeanObjectCache.put(beanName, object);
						}
					}
				}
				return object;
			}
		}
		else {
			Object object = doGetObjectFromFactoryBean(factory, beanName);
			if (shouldPostProcess) {
				try {
					object = postProcessObjectFromFactoryBean(object, beanName);
				}
				catch (Throwable ex) {
					throw new BeanCreationException(beanName, "Post-processing of FactoryBean's object failed", ex);
				}
			}
			return object;
		}
	}

  在这个方法里只做了一件事,就是返回的 bean 若是单例的,那就必须要保证全局唯一性,同时,也因为是单例的,所以不必重复创建,可以使用缓存来提高性能,也就是说已经加载过就要记录下来以便于下次复用,否则的话就直接获取。
  在 FactoryBeanRegistrySupport#doGetObjectFromFactoryBean() 方法中我们最终看到了我们想要寻找的方法 factory.getObject() ,代码如下:

	private Object doGetObjectFromFactoryBean(final FactoryBean<?> factory, final String beanName)
			throws BeanCreationException {

		Object object;
		try {
			//需要权限验证
			if (System.getSecurityManager() != null) {
				AccessControlContext acc = getAccessControlContext();
				try {
					// factory::getObject:函数式编程,其实就是调用 getObject() 方法
					object = AccessController.doPrivileged((PrivilegedExceptionAction<Object>) factory::getObject, acc);
				}
				catch (PrivilegedActionException pae) {
					throw pae.getException();
				}
			}
			else {
				// 直接调用 getObject() 方法
				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 声明为 FactoryBean 类型,则当提取 bean 时提取的并不是 FactoryBean,而是 FactoryBean 中对应的 getObject() 方法返回的 bean,而 doGetObjectFromFactoryBean() 正是实现这个功能的。但是在 FactoryBeanRegistrySupport#getObjectFromFactoryBean() 方法中 FactoryBeanRegistrySupport#doGetObjectFromFactoryBean() 得到 bean 以后并没有直接返回,而是接下来又做了些后处理操作,这个是做什么的?我们跟踪 FactoryBeanRegistrySupport#postProcessObjectFromFactoryBean() 方法进入:

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

  发现是直接返回 bean,啥操作没有,其实是因为真正并不是调用这个方法,而是被子类 AbstractAutowireCapableBeanFactory 重写了该方法。其中继承关系如:FactoryBeanRegistrySupport --> AbstractBeanFactory --> AbstractAutowireCapableBeanFactory。我们来看一下重写后的方法:AbstractAutowireCapableBeanFactory#postProcessObjectFromFactoryBean()

	@Override
	protected Object postProcessObjectFromFactoryBean(Object object, String beanName) {
		return applyBeanPostProcessorsAfterInitialization(object, beanName);
	}
	
	@Override
	public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
			throws BeansException {

		Object result = existingBean;
		for (BeanPostProcessor processor : getBeanPostProcessors()) {
			Object current = processor.postProcessAfterInitialization(result, beanName);
			if (current == null) {
				return result;
			}
			result = current;
		}
		return result;
	}

  对于后处理器的使用我们还未过多接触,后续章节会使用大量篇幅介绍,这里,我们只需了解在 Spring 获取 bean 的规则中有这样一条:尽可能保证所有 bean 初始化后都会调用注册的 BeanPostProcessor 的 postProcessAfterInitialization() 方法进行处理,在实际开发过程中大可以针对此特性设计自己的业务逻辑

发布了444 篇原创文章 · 获赞 113 · 访问量 40万+

猜你喜欢

转载自blog.csdn.net/panchang199266/article/details/101037446