Spring4源码分析之IOC(二)------Bean的加载

参考资料《Spring源码深度解析》

Bean的加载

追踪源码可以发现ApplicationContext.getBean()的内部实现是BeanFactory.getBean(),而BeanFactory.getBean()的内部实现是AbstractBeanFactory.getBean()。
流程如下
ApplicationContext.getBean()----》BeanFactory.getBean()----》AbstractBeanFactory.getBean()
即无论是ApplicationContext.getBean()还是BeanFactory.getBean()最后调用的都是AbstractBeanFactory.getBean() 方法。

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

而getBean()真正做事情的是doGetBean()

protected <T> T doGetBean(
			final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
			throws BeansException {
		//提取对应的beanName
		final String beanName = transformedBeanName(name);
		Object bean;

		// 先尝试从缓存或者singletonFactories中的ObjectFactory获取
		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 + "'");
				}
			}
			//有时候并不是放回实例本身,而是返回对应的实例。如:BeanFactory情况下返回指定方法返回的实例
			bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
		}

		else {
			// 原型模式的依赖检查,当原型模式有循环依赖时抛出异常
			if (isPrototypeCurrentlyInCreation(beanName)) {
				throw new BeanCurrentlyInCreationException(beanName);
			}

			// 如果本BeanFactory找不到就尝试从父BeanFactory中查找
			BeanFactory parentBeanFactory = getParentBeanFactory();
			if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
				String nameToLookup = originalBeanName(name);
				if (args != null) {
					return (T) parentBeanFactory.getBean(nameToLookup, args);
				}
				else {
					return parentBeanFactory.getBean(nameToLookup, requiredType);
				}
			}
			
			//如果不是仅仅做类型检查则是创建bean,这里进行记录
			if (!typeCheckOnly) {
				markBeanAsCreated(beanName);
			}
			
			try {
			//将存储XML配置文件的GernericBeanDefinition转换为RootBeanDefinition,吐过指定BeanName是子Bean的话同时会合并父类的相关属性
				final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
				checkMergedBeanDefinition(mbd, beanName, args);

				String[] dependsOn = mbd.getDependsOn();
				// 若存在依赖则递归实例化依赖的bean
				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);
						}
					}
				}

/****************************** 根据指定的模式进行bean的创建************************/
				//单例模式
				if (mbd.isSingleton()) {
					sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
						@Override
						public Object getObject() throws BeansException {
							try {
								return createBean(beanName, mbd, args);
							}
							catch (BeansException ex) {
								destroySingleton(beanName);
								throw ex;
							}
						}
					});
					bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
				}
				
				//原型模式
				else if (mbd.isPrototype()) {
					Object prototypeInstance = null;
					try {
						beforePrototypeCreation(beanName);
						prototypeInstance = createBean(beanName, mbd, args);
					}
					finally {
						afterPrototypeCreation(beanName);
					}
					bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
				}
				//其他指定的模式
				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, 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;
			}
		}

		// 检查所需的类型是否与实际bean实例的类型匹配,若不匹配做类型转换。
		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;
	}

大致流程如下
1:transformedBeanName(name) 转换为对应的beanName

2:getSingleton(beanName) 尝试从缓存中加载单例

3:getObjectForBeanInstance(prototypeInstance, name, beanName, mbd) 实例化从缓存中得到的Bean

4:isPrototypeCurrentlyIncreation(beanName) 原型模式的依赖检查

5:检测父BeanFactory

6:getMergedLocalBeanDefinition(beanName) GernericBeanDefinition转换为RootBeanDefinition

7:依赖检测

8:根据不同的模式创建bean

9:如果需要则做类型转换

哪一步是重中之重一目了然。
第8步,createBean() 根据不同的模式创建bean是实例化一个Bean的主要逻辑。

1:transformedBeanName(name) 转换为对应的beanName

protected String transformedBeanName(String name) {
		return canonicalName(BeanFactoryUtils.transformedBeanName(name));
	}

大概就是

  • 去除FactoryBean的修饰符,也就是如果name=“&aa”则去掉‘&’是name=“aa”
  • 别名转换

2:getSingleton(beanName) 尝试从缓存中加载单例

public Object getSingleton(String beanName) {
		//参数true设置标识允许早期依赖
		return getSingleton(beanName, true);
	}
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
		//检查缓存中是否存在实例
		Object singletonObject = this.singletonObjects.get(beanName);
		if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
			//如果为空,则锁定全局变量并进行处理
			synchronized (this.singletonObjects) {
				//如果正在加载,则不处理
				singletonObject = this.earlySingletonObjects.get(beanName);
				if (singletonObject == null && allowEarlyReference) {
					//当某些方法需要提取初始化的时候则会调用addSingletonFactory方法将对应的ObjectFactory初始化策略存储在singletionFactories
					ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
					if (singletonFactory != null) {
						//调用预先设定的getObject方法
						singletonObject = singletonFactory.getObject();
						//记录在缓存中,earlySingletonObjects和singletonFactories互斥
						this.earlySingletonObjects.put(beanName, singletonObject);
						this.singletonFactories.remove(beanName);
					}
				}
			}
		}
		return (singletonObject != NULL_OBJECT ? singletonObject : null);
	}

3:getObjectForBeanInstance(prototypeInstance, name, beanName, mbd) 实例化从缓存中得到的Bean

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

		if (BeanFactoryUtils.isFactoryDereference(name) && !(beanInstance instanceof FactoryBean)) {
			throw new BeanIsNotAFactoryException(transformedBeanName(name), beanInsta
			/*......*/
			/*中间省略*/
			/*......*/
			object = getObjectFromFactoryBean(factory, beanName, !synthetic);
		}
		return object;
	}

上面代码大都是一些辅助性的东西,真正有用的是getObjectFromFactoryBean()
而getObjectFromFactoryBean()真正有用的是doGetObjectFromFactoryBean()
因此直接到doGetObjectFromFactoryBean()

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

		Object object;
		try {
			if (System.getSecurityManager() != null) {
				AccessControlContext acc = getAccessControlContext();
				try {
					object = AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
						@Override
						public Object run() throws Exception {
								return 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 && isSingletonCurrentlyInCreation(beanName)) {
			throw new BeanCurrentlyInCreationException(
					beanName, "FactoryBean which is currently in creation returned null from getObject");
		}
		return object;
	}

找啊找发现重点 factory.getObject()
就是说如果bean是FactoryBean的话,则不是直接返回bean本身,而是FactoryBean中对应的getObject方法返回的bean。

4:isPrototypeCurrentlyIncreation(beanName) 原型模式的依赖检查

if (isPrototypeCurrentlyInCreation(beanName)) {
				throw new BeanCurrentlyInCreationException(beanName);
			}

原型模式下若存在循环依赖会导致内存泄漏等问题,所以这里要先做个检测,如果存在循环依赖就抛出异常。

5:检测父BeanFactory

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);
				}
			}

这一步就是当自身BeanFactory不包含Bean时尝试从父BeanFactory中加载Bean。

6:getMergedLocalBeanDefinition(beanName) GernericBeanDefinition转换为RootBeanDefinition

final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);

因为从XML配置文件中读取到的bean信息时存储在GernericBeanDefinition中的,但是所有的bean后续处理都是针对于RootBeanDefinition的,所以这里需要进行一个转换,转换的同时如果父类bean不为空的话,则会一并合并父类的属性。
至于怎么转换的就不深究了。。。

7:依赖检测

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);
						}
					}
				}

因为bean的初始化过程中很可能会用到某些属性,而某些属性很可能时动态配置的,且配置成依赖于其他的bean,那么这个时候就有必要先加载依赖的bean,所以,在Spring的加载顺序中,在初始化某一个bean的时候首先会初始化这个bean所对应的依赖。

8:根据不同的模式创建bean

以单例的加载为例

if (mbd.isSingleton()) {
					sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
						@Override
						public Object getObject() throws BeansException {
							try {
								return createBean(beanName, mbd, args);
							}
							catch (BeansException ex) {
								destroySingleton(beanName);
								throw ex;
							}
						}
					});
					bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}

可以发现主要逻辑在getSingleton(),而getSingleton又有一个匿名内部类作为参数,而这个匿名内部类主要逻辑在createBean()
即这一步有两个很重要的方法getSingleton()、createBean()

8.1 getSingleton()

public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
		Assert.notNull(beanName, "'beanName' must not be null");
		synchronized (this.singletonObjects) {
			//检测缓存中是否已经加载过
			Object singletonObject = this.singletonObjects.get(beanName);
			//若没有加载过才加载
			if (singletonObject == null) {
				if (this.singletonsCurrentlyInDestruction) {
					throw new BeanCreationNotAllowedException(beanName,
							"Singleton bean creation not allowed while singletons of this factory are in destruction " +
							"(Do not request a bean from a BeanFactory in a destroy method implementation!)");
				}
				if (logger.isDebugEnabled()) {
					logger.debug("Creating shared instance of singleton bean '" + beanName + "'");
				}
				//加载前记录加载状态
				beforeSingletonCreation(beanName);
				boolean newSingleton = false;
				boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
				if (recordSuppressedExceptions) {
					this.suppressedExceptions = new LinkedHashSet<Exception>();
				}
				try {
					//根据调用参数传入的ObjectFactory的个体Object方法实例化bean
					//即执行createBean()
					singletonObject = singletonFactory.getObject();
					newSingleton = true;
				}
				catch (IllegalStateException ex) {
					// Has the singleton object implicitly appeared in the meantime ->
					// if yes, proceed with it since the exception indicates that state.
					singletonObject = this.singletonObjects.get(beanName);
					if (singletonObject == null) {
						throw ex;
					}
				}
				catch (BeanCreationException ex) {
					if (recordSuppressedExceptions) {
						for (Exception suppressedException : this.suppressedExceptions) {
							ex.addRelatedCause(suppressedException);
						}
					}
					throw ex;
				}
				finally {
					if (recordSuppressedExceptions) {
						this.suppressedExceptions = null;
					}
					//加载单例后的处理方法调用
					afterSingletonCreation(beanName);
				}
				if (newSingleton) {
					//将结果加入缓存
					addSingleton(beanName, singletonObject);
				}
			}
			return (singletonObject != NULL_OBJECT ? singletonObject : null);
		}
	}

大致如下:

  • 检查缓存是否已经加载过
  • 若无,记录BeanName为正在加载状态
  • 加载单例前记录加载状态
  • 通过调用参数传入ObjectFactory的个体Object方法实例化bean(即调用createBean实例化bean)
  • 加载单例后的处理方法调用
  • 将结果加入缓存

这里主要分析createBean() 方法

8.1.1 createBean()
protected Object createBean(String beanName, RootBeanDefinition mbd, Object[] args) throws BeanCreationException {
		if (logger.isDebugEnabled()) {
			logger.debug("Creating instance of bean '" + beanName + "'");
		}
		RootBeanDefinition mbdToUse = mbd;

		//锁定class,根据设置的class属性或者根据calssName属性来解析class
		Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
		if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
			mbdToUse = new RootBeanDefinition(mbd);
			mbdToUse.setBeanClass(resolvedClass);
		}

		// 对lookup-method和replace-method属性的处理(指定方法的覆盖)
		try {
			mbdToUse.prepareMethodOverrides();
		}
		catch (BeanDefinitionValidationException ex) {
			throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
					beanName, "Validation of method overrides failed", ex);
		}

		try {
			// 调用后置处理器返回代理bean(只针对InstantiationAwareBeanPostProcessor的before)
			Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
			if (bean != null) {
				return bean;
			}
		}
		catch (Throwable ex) {
			throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
					"BeanPostProcessor before instantiation of bean failed", ex);
		}
		
		//真正的创建bean
		Object beanInstance = doCreateBean(beanName, mbdToUse, args);
		if (logger.isDebugEnabled()) {
			logger.debug("Finished creating instance of bean '" + beanName + "'");
		}
		return beanInstance;
	}

大致如下:

  • 根据设置的class属性或者根据calssName属性来解析class
  • 对lookup-method和replace-method属性的处理(指定方法的覆盖)
  • 调用后置处理器返回代理bean(只针对InstantiationAwareBeanPostProcessor 的before)

这一步从这个“Aware”就可以知道与ApplicationContextAware等接口一样让bean知道指定的事物。这里是指,让bean知道自己将要被创建,在这之前做些自定义操作。

  • doCreateBean() 真正的创建bean
8.1.1.1 doCreateBean()

另起一篇这里是链接

9:如果需要则做类型转换

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());
			}
		}

程序到这里返回bean后已经基本结束了,通常对该方法的调用参数requiredType是为空的,但是可能会存在这样的情况,返回的bean其实是个String,但是requiredType却传入Integer的类型,那么这时候本步骤就会起作用了,它的功能是将返回的bean转换为requiredType所指定的类型。当然,String转换为Integer时最简单的一种转换,在Spring中提供了各种各样的转换器,用户也可以自己扩展转换器来满足需求。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值