Springframework源码解析-doGetBean源码详解

只有单例模式才会尝试解决循环依赖,如果存在A中有B的属性,B中有A的属性,那么当依赖注入的时候看,就会产生当A还未创建完的时候因为对于B的创建再次返回创建A,造成循环依赖,也就是情况:isPrototypeCurrentlyInCreation(beanName)判断为true。如果缓存中没有单例Bean的缓存,则需要从头开始创建单例Bean,这主要是重载getSingleton的重载方法来实现单例Bean的加载。通过给定的bean实例获取对象,返回的bean为自己或者是FactoryBean创建的对象。
摘要由CSDN通过智能技术生成

1. doGetBean方法源码解析

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

		/**
		 * 通过name获取BeanName,这里不能使用name作为beanName:
		 * 1. name可能是别名,通过方法转换为具体的实例名称
		 * 2. name可能会以&开头,表明调用者想获取FactoryBean本身,而非FactoryBean创建bean
		 *    FactoryBean 的实现类和其他的 bean 存储方式是一致的,即 <beanName, bean>,
		 *    beanName 中是没有 & 这个字符的。所以我们需要将 name 的首字符 & 移除,这样才能从
		 *    缓存里取到 FactoryBean 实例。
		 *
		 */
		final String beanName = transformedBeanName(name);
		Object bean;

		// 从缓存中获取bean
		Object sharedInstance = getSingleton(beanName);

		/*
		 * 如果 sharedInstance = null,则说明缓存里没有对应的实例,表明这个实例还没创建。
		 *( BeanFactory 并不会在一开始就将所有的单例 bean 实例化好,而是在调用 getBean 获取bean 时再实例化,也就是懒加载)。
		 * getBean 方法有很多重载,比如 getBean(String name, Object... args),我们在首次获取
		 * 某个 bean 时,可以传入用于初始化 bean 的参数数组(args),BeanFactory 会根据这些参数
		 * 去匹配合适的构造方法构造 bean 实例。当然,如果单例 bean 早已创建好,这里的 args 就没有
		 * 用了,BeanFactory 不会多次实例化单例 bean。
		 */
		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 + "'");
				}
			}

			/*
			 * 如果 sharedInstance 是普通的单例 bean,下面的方法会直接返回。但如果
			 * sharedInstance 是 FactoryBean 类型的,则需调用 getObject 工厂方法获取真正的
			 * bean 实例。如果用户想获取 FactoryBean 本身,这里也不会做特别的处理,直接返回
			 * 即可。毕竟 FactoryBean 的实现类本身也是一种 bean,只不过具有一点特殊的功能而已。
			 */
			bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
		}

		/*
		 * 如果上面的条件不满足,则表明 sharedInstance 可能为空,此时 beanName 对应的 bean
		 * 实例可能还未创建。这里还存在另一种可能,如果当前容器有父容器,beanName 对应的 bean 实例
		 * 可能是在父容器中被创建了,所以在创建实例前,需要先去父容器里检查一下。
		 */
		else {
			// BeanFactory 不缓存 Prototype 类型的 bean,无法处理该类型 bean 的循环依赖问题
            //判断是否存在循环依赖
			if (isPrototypeCurrentlyInCreation(beanName)) {
				throw new BeanCurrentlyInCreationException(beanName);
			}

			// 如果 sharedInstance = null,则到父容器中查找 bean 实例
			BeanFactory parentBeanFactory = getParentBeanFactory();
			if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
				// Not found -> check parent.
				String nameToLookup = originalBeanName(name);
				if (parentBeanFactory instanceof AbstractBeanFactory) {
					return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
							nameToLookup, requiredType, args, typeCheckOnly);
				}
				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);
				}
			}

			if (!typeCheckOnly) {
				markBeanAsCreated(beanName);
			}

			try {
				// 合并父 BeanDefinition 与子 BeanDefinition
				final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
				checkMergedBeanDefinition(mbd, beanName, args);

				// 检查是否有 dependsOn 依赖,如果有则先初始化所依赖的 bean
				String[] dependsOn = mbd.getDependsOn();
				if (dependsOn != null) {
					for (String dep : dependsOn) {

						/*
						 * 检测是否存在 depends-on 循环依赖,若存在则抛异常。比如 A 依赖 B,
						 * B 又依赖 A,他们的配置如下:
						 *   <bean id="beanA" class="BeanA" depends-on="beanB">
						 *   <bean id="beanB" class="BeanB" depends-on="beanA">
						 *
						 * beanA 要求 beanB 在其之前被创建,但 beanB 又要求 beanA 先于它
						 * 创建。这个时候形成了循环,对于 depends-on 循环,Spring 会直接
						 * 抛出异常
						 */

						if (isDependent(beanName, dep)) {
							throw new BeanCreationException(mbd.getResourceDescription(), beanName,
									"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
						}
						// 注册依赖记录
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
org.springframework.core-3.1.0是Spring框架的一个核心模块,用于提供核心的功能和工具。它包含了一些基础类和接口,用于支持Spring框架的其他模块的运行。 其中,org.springframework.core-3.1.0模块包括以下几个重要的功能: 1. 依赖注入机制:org.springframework.core-3.1.0提供了Spring框架中的依赖注入机制。通过使用它提供的注解和配置方式,可以实现对象之间的解耦和依赖关系的管理,从而降低代码的耦合度,提高代码的可重用性和可维护性。 2. 类型转换:org.springframework.core-3.1.0还提供了类型转换的功能。它包含了一些类型转换的工具类,可以方便地进行各种类型之间的转换操作,如字符串到数字的转换、日期类型的转换等。 3. 资源管理:org.springframework.core-3.1.0提供了资源管理的功能。它包含了一些基础的资源接口和实现类,用于加载和管理应用程序中的各种资源,如文件、URL、类路径下的资源等。 4. 注解处理:org.springframework.core-3.1.0还提供了注解处理的功能。它包含了一些注解处理的工具类和接口,可以方便地进行注解的解析和处理,实现一些特定的功能,如AOP切面、事务管理等。 总之,org.springframework.core-3.1.0是Spring框架中一个非常重要的核心模块,提供了许多基础的功能和工具,用于支持整个Spring框架的运行和扩展。它的存在为开发人员提供了便捷的开发方式和丰富的功能选择,提高了软件开发的效率和质量。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值