Spring Bean的实例化

Bean的实例化

上一文简单理了一下容器创建,本文说一下实例化过程

  • 测试代码
 //容器的创建
 BeanFactory beanFactory = new XmlBeanFactory(resource);
 //实例化
 MyTestBean myTestBean = (MyTestBean) beanFactory.getBean("myTestBean");
  • 代码分析
    AbstractBeanFactory 中
public Object getBean(String name) throws BeansException {
	return doGetBean(name, null, null, false);
}

protected <T> T doGetBean(
			final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
			throws BeansException {
	//返回规范的bean名称
	final String beanName = transformedBeanName(name);
	Object bean;

 //尝试从缓存中获取Bean
 //Spring是使用Map作为beanName和bean实例的缓存的,可以简单的理解为beanMap.get(beanName)
	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 + "'");
			}
		}
		//根据 name 返回相应的 bean 实例,即返回 FactoryBean 或 普通 bean
		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);
		}

		// 检查工厂中是否有这个bean
		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) {
			//标记bean为创建或即将创建
			markBeanAsCreated(beanName);
		}

		try {
			/*
            * 根据 Bean 的名字取得 BeanDefinition
            * 合并父 BeanDefinition 与子 BeanDefinition
            *  <bean id="user" class="com.spring.learn.pojo.User">
            * 		 <property name="username" value="TT"/>
            *		 <property name="age" value="25" />
            * 	<bean/>
            *  <!-- user-child 配置继承自, user user-child未配置class属性 -->
            * 	<bean id="user-child" parent="user">
            * 		<property name="username" value="TT_child"/>
            *		<property name="age" value="13" />
            * 	<bean/>
            * 
            *  applicationContext.getBean("user-child"); //User{username='TT_child' ,age=13}
            *
            *  user-child 在未配置 class 的属性下也实例化成功
            */
			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);
					try {
						getBean(dep);
					}
					catch (NoSuchBeanDefinitionException ex) {
						throw new BeanCreationException(mbd.getResourceDescription(), beanName,
								"'" + beanName + "' depends on missing bean '" + dep + "'", ex);
					}
				}
			}

			// 实例化对象
			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()) {
				//Prototype下的实例化
				Object prototypeInstance = null;
				try {
					beforePrototypeCreation(beanName);
					prototypeInstance = createBean(beanName, mbd, args);
				}
				finally {
					afterPrototypeCreation(beanName);
				}
				bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
			}

			else {
				//request,session, globalsession下的实例化
				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;
		}
	}

	// 如果创建时加了类型参数,会校验类型是否匹配,
	//如 beanFactory.getBean("myTestBean",MyTestBean.class);
	if (requiredType != null && bean != null && !requiredType.isInstance(bean)) {
		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;
}

到这里,我们基本了解getBean他是怎么玩的了
1 直接调用 doGetBean()方法;
2 转换 name ,获取真正的 beanName;
3 从缓存中获取 bean 实例
4 若获取到了,则调用 getObjectForBeanInstance() ,根据 name 返回相应的 bean 实例,即返回 FactoryBean 或 普通 bean
5 若没获取到,则递归的去父容器中查找 beanName 对有的 bean 实例, 若父容器存在,则直接返回
6 若父容器也不存在,则真的需要新建 bean 实例了,先合并 BeanDefinition
7 关联depends-on所有依赖
8 根据作用域创建 bean 实例 ,并加入缓存
9 再调用 getObjectForBeanInstance() ,根据 name 返回相应的 bean 实例 ,与步骤四作用相同
10 按需转换 bean 类型,并返回转换后的 bean 实例

假如缓存中没有,创建bean的方法是 getObjectForBeanInstance(),继续跟进代码

protected Object getObjectForBeanInstance(
			Object beanInstance, String name, String beanName, RootBeanDefinition mbd) {

		// Don't let calling code try to dereference the factory if the bean isn't a factory.
		if (BeanFactoryUtils.isFactoryDereference(name) && !(beanInstance instanceof FactoryBean)) {
			throw new BeanIsNotAFactoryException(transformedBeanName(name), beanInstance.getClass());
		}

		// 返回bean实例 或者 对应的FactoryBean 实例   
		// name如果 是以 "&"开头的,说明是工厂实例
		if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {
			return beanInstance;
		}

		Object object = null;
		if (mbd == null) {
			//类型为null,根据beanName 从缓存中获取 bean
			object = getCachedObjectForFactoryBean(beanName);
		}
		if (object == null) {
			// 程序能执行到这里,说明beanInstance是个FactoryBean
			FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
			
			if (mbd == null && containsBeanDefinition(beanName)) {
				mbd = getMergedLocalBeanDefinition(beanName);
			}
			boolean synthetic = (mbd != null && mbd.isSynthetic());
			//从工厂实例中根据beanName获取需要的实例
			object = getObjectFromFactoryBean(factory, beanName, !synthetic);
		}
		return object;
	}

getObjectForBeanInstance() 方法从 FactoryBean 中获取 bean 的步骤如下:
1.判断 beanInstance 的类型,如果是普通 bean,则直接返回
2.如果 bean 是 FactoryBean 类型,则先从缓存里获取 FactoryBean 生成的实例 ,若缓存中存在则直接返回
3.若缓存中不存在,用 getObjectFromFactoryBean 从工厂中获取 bean实例
另外说明一下,如果 FactoryBean 为单例,调用 FactoryBean.getObject() 方法生成实例的时候,会把实例bean一并放入缓存中

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值