Spring源码解读(四)Bean创建过程之加载——AbstractBeanFactory

前言

上文 Spring源码解读(三)Bean创建过程之注册——DefaultListableBeanFactory 中,已经分析到了DefalutListableBeanFactory将所有的Bean注册到自己的注册表中,这篇文章暂时跳过refresh()方法中的其他步骤,从getBean()方法入手,分析bean创建的逻辑。refresh()中其他逻辑在后续文章中分析。

代码入口

ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
ac.getBean("");

直接从 ac.getBean() 点进去,看其内部逻辑。

	@Override
	public Object getBean(String name) throws BeansException {
		// 断言,判断上下文的 BeanFactory 当前处于活动状态,非活动状态抛出异常
		assertBeanFactoryActive();
		// 获取在AbstractRefreshableApplicationContext.refreshBeanFactory方法中创建的DefaultListableBeanFactory对象
		// 从DefaultListableBeanFactory对象中获取注册表中缓存的bean
		// 再由BeanFactory的实现类进行具体的创建过程
		// 再次提醒 DefaultListableBeanFactory springBean的核心
		// getBeanFactory是一个抽象方法,返回值是ConfigurableListableBeanFactory接口类型
		// AbstractRefreshableApplicationContext继承了AbstractApplicationContext, 实现了getBeanFactory
		return getBeanFactory().getBean(name);
	}

获取BeanFactory

AbstractRefreshableApplicationContext#getBeanFactory

方法内部逻辑很简单,就直接返回这个对象中的成员变量beanFactory。这个属性就是由refreshBeanFactory方法创建的,如果对这个方法不熟悉可以看 Spring源码解读(一)启动流程分析 ,这里做了详细的介绍,并多次提到DefaultListableBeanFacory。

	@Override
	public final ConfigurableListableBeanFactory getBeanFactory() {
		// 返回 refreshBeanFactory() 方法创建的 beanFactory
		DefaultListableBeanFactory beanFactory = this.beanFactory;
		if (beanFactory == null) {
			throw new IllegalStateException("BeanFactory not initialized or already closed - " +
					"call 'refresh' before accessing beans via the ApplicationContext");
		}
		return beanFactory;
	}

这里getBeanFactory拿到的DefaultListableBeanFactory是ConfigurableListableBeanFactory接口的实现类,调用getBean方法,getBean方法是由BeanFactory顶级接口定义的,AbstractBeanFactory实现了BeanFactory接口,同时提供了一些通用的默认实现,所以DefaultListableBeanFactory.getBean实际调用的就是AcstractBeanFactory的通用实现。如果对这部分不清楚可以看上一篇博文 Spring源码解读(三)Bean创建过程之注册——DefaultListableBeanFactory 中介绍DefaultListableBeanFactory父类和接口的功能。

获取Bean入口

AbstractBeanFactory#getBean

通过beanName获取bean对象,此时不知道bean是什么类型,返回的是Object对象,使用时需要做类型转换。

	@Override
	public Object getBean(String name) throws BeansException {
		return doGetBean(name, null, null, false);
	}

AbstractBeanFactory#doGetBean

doGetBean是AcstractBeanFactory自己的方法,支持通过beanName、类型获取bean。

它优先从单例缓存中查找bean,如果有直接返回;如果没有,则根据不同的作用域创建bean实例,然后返回。

	protected <T> T doGetBean(
			String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
			throws BeansException {
		// 此时不知道传递的beanName是主名还是别名
		// 通过这一步转换,拿到bean的主名
		String beanName = transformedBeanName(name);
		Object bean;

		// 优先从单例缓存中获取bean
		// 在创建单例Bean时,如果bean存在依赖注入的情况,而在创建依赖的时候为了避免循环依赖
		// Spring创建Bean的原则是 不等bean创建完成就会创建bean的ObjectFactory,提前曝光
		// 提前将ObjectFactory加入到缓存中,等下一个bean创建时需要依赖这个类的直接使用ObjectFactory
		// Eagerly check singleton cache for manually registered singletons.
		Object sharedInstance = getSingleton(beanName);
		if (sharedInstance != null && args == null) {
			if (logger.isTraceEnabled()) {
				// 这个bean是否正在创建中
				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 + "'");
				}
			}
			// 获取这个bean的实例对象
			// 这个方法是为了处理FactoryBean的子类,如果没有实现FactoryBean就直接返回
			// 因为FactoryBean要通过getObject方法才能返回bean的实例
			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,创建B时又会去创建A,这就是循环依赖。
			// 所以 只有单列模式下才能解决循环依赖,因为单例模式的bean是共享的。
			// 当多例模式的情况下,无法解决,如果存在循环依赖,只能抛出异常
			// 下面就是判断多例情况下,是不是正在被创建 存在循环依赖的情况。
			if (isPrototypeCurrentlyInCreation(beanName)) {
				throw new BeanCurrentlyInCreationException(beanName);
			}

			// Check if bean definition exists in this factory.
			BeanFactory parentBeanFactory = getParentBeanFactory();
			// 是否有BeanDefinition,如果有就不需要再创建BeanDefinition
			if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
				// Not found -> check parent.
				// bean的原名,用于父级工厂中查找
				String nameToLookup = originalBeanName(name);
				// 委托父级工厂获取Bean对象
				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);
				}
			}

			// 类型检查,主要是判断是否在创建bean,
			// 如果不仅仅做检查的话,就是在创建bean,要标记状态
			if (!typeCheckOnly) {
				// 将bean 标记为已创建或即将创建
				markBeanAsCreated(beanName);
			}

			try {
				// 转换为RootBeanDefinition,
				// 如果是子bean的话,同时合并父类属性
				RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
				checkMergedBeanDefinition(mbd, beanName, args);

				// Guarantee initialization of beans that the current bean depends on.
				// dependsOn AbstractBeanDefinition定义的成员属性,其存放的值是<bean>标签中的depends-on属性的值,或者被@DependsOn注解的值
				// 这里的依赖不是指普通的@Autowire的依赖
				String[] dependsOn = mbd.getDependsOn();
				// 处理当前bean的依赖,保证它依赖的bean都被初始化
				if (dependsOn != null) {
					for (String dep : dependsOn) {
						// 当前bean的依赖是否已经注册到注册表中,可能存在循环依赖
						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);
						}
					}
				}

				// 开始创建bean实例
				// Create bean instance.
				if (mbd.isSingleton()) {
					// 调用DefaultSingletonBeanRegistry.getSingleton获取单例对象实例
					// 这个方法的参数时,beanName 和 ObjectFactory, 这里new一个匿名实现类
					sharedInstance = getSingleton(beanName, () -> {
						try {
							// 调用AbstractAutowireCapableBeanFactory.createBean
							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);
						// 调用AbstractAutowireCapableBeanFactory.createBean
						prototypeInstance = createBean(beanName, mbd, args);
					}
					finally {
						// 创建后置操作,取消标记当前bean的正在创建状态
						afterPrototypeCreation(beanName);
					}
					// 获取这个bean的实例对象
					bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
				}

				else {
					String scopeName = mbd.getScope();
					// 作用域参数 有效性验证
					if (!StringUtils.hasLength(scopeName)) {
						throw new IllegalStateException("No scope name defined for bean '" + beanName + "'");
					}

					// this.scopes是一个Map, AbstractBeanFactory.registerScope 为scopes赋值
					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) {
				// 创建失败后清除,从alreadyCreated删除
				cleanupAfterBeanCreationFailure(beanName);
				throw ex;
			}
		}

		// 类型检查,已经创建的bean和实际需要类型是否一致
		// Check if required type matches the type of the actual bean instance.
		if (requiredType != null && !requiredType.isInstance(bean)) {
			try {
				// 类型转换,如果这个bean无法转换成所需的类型,返回null,表示类型不一致,抛出异常
				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;
	}

转换beanName

AbstractBeanFactory#transformedBeanName

调用这个方法时,传入的字符串目前我们无法得知是主名还是别名,需要通过aliasMap进行转换,同时也处理FactoryBean的修饰符“&”。

aliasMap是一个缓存主名和别名映射关系的Map,那么它是怎么来的呢?

在上一篇博文中有提到BeanDefinitionReaderUtils这个工具类,aliasMap就是在它的registerBeanDefinition方法的最后一步,调用SimpleAliasRegistry.registerAlias方法完成维护主名和别名的映射关系。

	protected String transformedBeanName(String name) {
		// BeanFactoryUtils.transformedBeanName 处理FactoryBean通过 & + beanName的方式获取bean
		return canonicalName(BeanFactoryUtils.transformedBeanName(name));
	}

	public String canonicalName(String name) {
		String canonicalName = name;
		// Handle aliasing...
		String resolvedName;
		do {
			// aliasMap 在bean注册的过程中,会将bean主名和别名添加到aliasMap中 做好映射关系
			// 这里通过传入的名字在映射关系中查询到主名称
			resolvedName = this.aliasMap.get(canonicalName);
			if (resolvedName != null) {
				canonicalName = resolvedName;
			}
		}
		while (resolvedName != null);
		return canonicalName;
	}

	public static void registerBeanDefinition(
			BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
			throws BeanDefinitionStoreException {

		// 主beanName
		// Register bean definition under primary name.
		String beanName = definitionHolder.getBeanName();
		// 使用此注册表注册一个新的 BeanDefinition。
		registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());

		// 如果有别名,注册别名
		// Register aliases for bean name, if any.
		String[] aliases = definitionHolder.getAliases();
		if (aliases != null) {
			for (String alias : aliases) {
				// 为这个bean设置别名, 调用SimpleAliasRegistry.registerAlias方法完成
				registry.registerAlias(beanName, alias);
			}
		}
	}

优先从缓存中获取bean

DefaultSingletonBeanRegistry#getSingleton(java.lang.String)

获取bean时,优先从单例缓存中获取bean。因为单例bean只会被创建一次,获取bean时优先从单例缓存中取,如果缓存中不存的,可能会存在循环依赖的问题,这时可以直接创建这个bean,并允许提前引用当前创建的单例,从而解决循环引用。

	@Nullable
	protected Object getSingleton(String beanName, boolean allowEarlyReference) {
		// Quick check for existing instance without full singleton lock
		// 检查缓存中是否存在实例
		Object singletonObject = this.singletonObjects.get(beanName);
		if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
			// 如果是null,并且正在加载中
			singletonObject = this.earlySingletonObjects.get(beanName);
			if (singletonObject == null && allowEarlyReference) {
				// 如果没有这个实例,
				synchronized (this.singletonObjects) {
					// Consistent creation of early reference within full singleton lock
					// 拿到锁后,创建早期引用
					singletonObject = this.singletonObjects.get(beanName);
					if (singletonObject == null) {
						singletonObject = this.earlySingletonObjects.get(beanName);
						if (singletonObject == null) {
							// 当某些方法需要提前初始化的时候则会调用 addSingletonFactory方法将对于的ObjectFactory初始化策略存储在SingletonFactories
							ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
							if (singletonFactory != null) {
								// 调用预先设定的getObject方法
								singletonObject = singletonFactory.getObject();
								// 记录在缓存中
								this.earlySingletonObjects.put(beanName, singletonObject);
								// earlySingletonObjects 和 singletonFactories 互斥
								this.singletonFactories.remove(beanName);
							}
						}
					}
				}
			}
		}
		return singletonObject;
	}

简单介绍一下这里设计到的几个Map缓存:

  • singletonObjects :缓存beanName和bean实例 ,key:beanName,value:beanInstance
  • singletonFactories : 缓存beanName和beanFactory,key:beanName, vaule:ObjectFactory
  • earlySingletonObjects :跟singletonObjects相同的地方是都是用来缓存beanName和bean实例的,不同点在于当一个单例的bean被放在earlySingletonObjects后,那么当bean还是在创建过程中,就可以通过getBean方法取到,目的就是为了处理循环依赖。
  • registeredSingletons :用来缓存当前已经注册的bean。

这个方法内涉及到spring经典的三级缓存,三级缓存简单的讲就是通过上面几个map集合实现的,关于三级缓存可参考 Spring源码解读(六)循环依赖及三级缓存源码分析——DefaultSingletonBeanRegistry

首先尝试从singletonObjects离获取,如果没有再从earlySingleton中获取,如果还是没有,再从singletonFactories中通过beanName找到对应的objectFactory,并调用其getObject方法创建bean; 最后加入到singletonObjects,同时从singletonFactories中删除,因为单例bean只会被创建一次,所有两者是互斥的。当然这一切的前提都是在 allowEarlyReference=true,也就是允许提前引用的情况下才会执行的。

获取bean的实例化

AbstractBeanFactory#getObjectForBeanInstance

如果在单例缓存中已经拿到的bean的实例对象,为什么还要再调用getObjectForBeanInstance?

其实后面不同作用域的bean实例化都在调用这个方法,这个方法主要是用来FactoryBean的。

这里需要提到两个基础接口BeanFactory和FactoryBean, 名字很像,功能区别很大。

  • BeanFactory 是定义Spring IOC容器的最基础的规范,只是个接口,有DefalutLisbleBeanFactory, AbstractBeanFactory等诸多实现。
  • FactoryBean 是Spring提供的一种更灵活的创建bean的方式,可以自定义复杂的Bean对象的实例化和初始化。

这个方法中,判断对象如果不是FactoryBean类型,就直接返回这个实例对象。只针对FactoryBean的实现类进行处理。

关于FactoryBean的细节问题,这里暂时不做讲解。

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

		// 如果beanName已 & 开头,检查是否FactoryBean的派生类。
		if (BeanFactoryUtils.isFactoryDereference(name)) {
			if (beanInstance instanceof NullBean) {
				return beanInstance;
			}
			if (!(beanInstance instanceof FactoryBean)) {
				// 如果不是派生类,就抛出异常
				throw new BeanIsNotAFactoryException(beanName, beanInstance.getClass());
			}
			if (mbd != null) {
				mbd.isFactoryBean = true;
			}
			return beanInstance;
		}


		if (!(beanInstance instanceof FactoryBean)) {
			// 不是FactoryBean 直接返回
			return beanInstance;
		}

		Object object = null;
		if (mbd != null) {
			mbd.isFactoryBean = true;
		}
		else {
			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());
			object = getObjectFromFactoryBean(factory, beanName, !synthetic);
		}
		return object;
	}

多例模式下循环依赖检查

AbstractBeanFactory#isPrototypeCurrentlyInCreation

检查多例(原型)类型是否存在循环依赖,spring目前无法解决多列模式下的循环依赖问题,因为单例模式bean是共享的,多例Bean不是共享的。

	protected boolean isPrototypeCurrentlyInCreation(String beanName) {
		Object curVal = this.prototypesCurrentlyInCreation.get();
		// 根据当前线程中的多例对象集合判断,如果存在这个多例bean,则bean正在创建中,此时就可能出现了循环依赖
		return (curVal != null &&
				(curVal.equals(beanName) || (curVal instanceof Set && ((Set<?>) curVal).contains(beanName))));
	}

委托父级工厂创建Bean

如果当前工厂类存在父级工厂,同时父级工厂中也有这个bean的装饰类BeanDefinition,就委托父级工厂获取bean。

标记创建状态

AbstractBeanFactory#markBeanAsCreated

标记bean正在被创建

			// 类型检查,主要是判断是否在创建bean,
			// 如果不仅仅做检查的话,就是在创建bean,要标记状态
			if (!typeCheckOnly) {
				// 将bean 标记为已创建或即将创建
				markBeanAsCreated(beanName);
			}


	protected void markBeanAsCreated(String beanName) {
		if (!this.alreadyCreated.contains(beanName)) {
			synchronized (this.mergedBeanDefinitions) {
				if (!this.alreadyCreated.contains(beanName)) {
					// 既然我们实际上是在创建 bean,就让 bean 定义重新合并,以防万一它的一些元数据同时发生变化。
					clearMergedBeanDefinition(beanName);
					this.alreadyCreated.add(beanName);
				}
			}
		}
	}

转换RootBeanDefinition

AbstractBeanFactory#getMergedLocalBeanDefinition

因为后续的处理都是针对RootBeanDeginition所以这里提起转换。

子类需要父类可被继承的属性,实例化时需要合并父类属性,同时从mergedBeanDeifition中取出这个bean的RootBeanDefinition。

最终在AbstractBeanFactory#getMergedBeanDefinition(String, BeanDefinition, BeanDefinition)完成合并,细节暂不分析

protected RootBeanDefinition getMergedLocalBeanDefinition(String beanName) throws BeansException {
		RootBeanDefinition mbd = this.mergedBeanDefinitions.get(beanName);
		if (mbd != null && !mbd.stale) {
			return mbd;
		}
		return getMergedBeanDefinition(beanName, getBeanDefinition(beanName));
	}

处理bean的依赖

注意这里的依赖不是指bean中@Autowire这种依赖,这里的depends-on是AbstractBeanDefinition定义的成员属性,其存放的值是<bean>标签中的depends-on属性的值,或者被@DependsOn注解的值。

保证当前bean实例化之前,它依赖的bean都被初始化。所以Spring在初始化某一个bean的时候,会先初始化这个bean所对于的依赖。

				// dependsOn AbstractBeanDefinition定义的成员属性,其存放的值是<bean>标签中的depends-on属性的值,或者被@DependsOn注解的值
				// 这里的依赖不是指普通的@Autowire的依赖
				String[] dependsOn = mbd.getDependsOn();
				// 处理当前bean的依赖,保证它依赖的bean都被初始化
				if (dependsOn != null) {
					for (String dep : dependsOn) {
						// 当前bean的依赖是否已经注册到注册表中,可能存在循环依赖
						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);
						}
					}
				}

根据不同作用域处理bean的创建

这部分内容在下一篇博文分析。

类型检查

当各Score实现类创建好bean以后,检查当前创建的bean类型和所需的类型是否一致。

		// 类型检查,已经创建的bean和实际需要类型是否一致
		if (requiredType != null && !requiredType.isInstance(bean)) {
			try {
				// 类型转换,如果这个bean无法转换成所需的类型,返回null,表示类型不一致,抛出异常
				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

最后返回创建好的bean,至此我们就可以通过beanName获取到Spring容器中的bean了。

		return (T) bean;

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值