spring源码:bean的加载

spring源码:bean的加载

测试代码

//xml配置文件的解析
ClassPathResource resource = new ClassPathResource("spring.xml");
		BeanFactory beanFactory = new XmlBeanFactory(resource);
		//bean的加载,这篇文章就是讲解这一句代码
		MyTestBean myTestBean = (MyTestBean) beanFactory.getBean("myTestBean");
		System.out.println(myTestBean.getTestStr());

跟踪入口

通过跟踪AbstractBeanFactory类的getBean(String name);

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

找到实际加载函数是doGetBean()方法
去掉干扰代码,只看主要代码

protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
			@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
		//1.转换对应的beanName
		final String beanName = transformedBeanName(name);
		Object bean;

		//2. 直接从三级缓存(单例对象、单例提前曝光的对象、单例对象工厂)中获取bean实例
		Object sharedInstance = getSingleton(beanName);
		if (sharedInstance != null && args == null) {
			//3.返回bean,有时候并不是直接返回实例本身,而是返回指定方法返回的实例
			bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
		}

		else {
			// 4. 原型模式的依赖检查,例如A还未创建完成的时候 因为B的创建 再次创建A,就会造成循环依赖
			//当isPrototypeCurrentlyInCreation=true时,也就是说当前bean正在创建中,也就时说明存在循环依赖
			if (isPrototypeCurrentlyInCreation(beanName)) {
				throw new BeanCurrentlyInCreationException(beanName);
			}

			//5.如果beanDefinitionMap中也就是所有已经加载的类中不包括beanName则尝试从parentBeanFactory中查找
			BeanFactory parentBeanFactory = getParentBeanFactory();
			if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
				//  // 如果没有,查询父工厂
				String nameToLookup = originalBeanName(name);
				if (parentBeanFactory instanceof AbstractBeanFactory) {
					return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
							nameToLookup, requiredType, args, typeCheckOnly);
				}
				else if (args != null) {
					// // 执行带有args参数的getbean方法
					return (T) parentBeanFactory.getBean(nameToLookup, args);
				}
				else {
					// 如果没有参数,执行标准的getbean方法
					return parentBeanFactory.getBean(nameToLookup, requiredType);
				}
			}
			//如果不仅仅是做类型检查,那么需要标记此Bean正在创建之中
			if (!typeCheckOnly) {
				markBeanAsCreated(beanName);
			}

			try {
				// 6.将存储xml的GernericBeanDefinition转换为RootBeanDefinition
				final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
				//如果beanName对应的类是子类的话,则会合并父类的相关属性
				checkMergedBeanDefinition(mbd, beanName, args);

				// 7. 获取依赖的Bean
				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);
						}
					}
				}

				//8.针对不同的scope进行bean的创建
				// 创建单例bean
				if (mbd.isSingleton()) {
					sharedInstance = getSingleton(beanName, () -> {
						try {
							return createBean(beanName, mbd, args);
						}
						catch (BeansException ex) {
							destroySingleton(beanName);
							throw ex;
						}
					});
					bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
				}

				else if (mbd.isPrototype()) {
					// It's a prototype -> create a new instance.
					Object prototypeInstance = null;
					try {
						//把当前的beanName加入正在创建beanName的集合中,会在第一步判断
						beforePrototypeCreation(beanName);
						prototypeInstance = createBean(beanName, mbd, args);
					}
					finally {
						//把当前的beanName从正在创建beanName的集合中移除
						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, () -> {
							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;
			}
		}

		// 9.检查类型,如果不满足可以进行类型转换,如果转换器进行不了这两种类型的转换,则抛出异常
		//将bean转换成requiredType所指定的类型
		if (requiredType != null && !requiredType.isInstance(bean)) {
			try {
				T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);
				if (convertedBean == null) {
					throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
				}
				return convertedBean;
			}
			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;
	}

从上面源码中可以看到,bean的加载主要是这九步。下面就会一步一步的讲解这九步。我们可以先不要深究这个方法中的代码,先从整体了解一下这个方法的主题结构。

1. 转换对应的beanName

实现方法: transformedBeanName(name)
返回值:真实的beanName
方法说明:doGetBean方法传入的name,可能并不是beanName,也可能是别名或者是FactoryBean,如果是别名alias,则需要找到对应的beanName;如果是FactoryBean,则需要去除name中&符。

2. 从缓存中加载单例

实现方法: getSingleton(beanName);
返回值:beanName对应的单例对象sharedInstance
方法说明:单例在spring同一容器中只会被创建一次,后续直接就从单例缓存中获取。
下面是该方法源码:
DefaultSingletonBeanRegistry.java

protected Object getSingleton(String beanName, boolean allowEarlyReference) {
		//1.从单例缓存中获取实例
		Object singletonObject = this.singletonObjects.get(beanName);
		//isSingletonCurrentlyInCreation判断此单例是否正在创建
		//检查这个bean是不是null,并且这个bean正在创建中的bean的map缓存(singletonsCurrentlyInCreation)中
		if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
			//走到这里证明,bean不在单例缓存中,而且有程序在创建beanName
			//则锁住单例缓存
			synchronized (this.singletonObjects) {
				// 2.从提前暴光的单例对象缓存中获取 bean
				singletonObject = this.earlySingletonObjects.get(beanName);
				if (singletonObject == null && allowEarlyReference) {
					// 都没有
					// 3.从单例工厂的缓存中找到对应的单例工厂生产提前暴光的单例
					ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
					if (singletonFactory != null) {
						//生产单例bean
						singletonObject = singletonFactory.getObject();
						//添加提前暴光的单例的缓存中
						this.earlySingletonObjects.put(beanName, singletonObject);
						//移除对应bean工厂
						this.singletonFactories.remove(beanName);
					}
				}
			}
		}
		return singletonObject;
	}

代码 中的注释已经很详细了,不在赘述。
值得一说的是,为什么要这么多层缓存?其实是为了检测是否涉及循环依赖。
singletonObjects:用于保存BeanName和创建的bean实例,是个Map对象。
singletonFactories:用户保存beanName和创建bean的工厂,是个Map对象。
earlySingletonObjects:用户保存beanName和创建的bean实例,与singletonObjects不同的是,这里面放的bean还在创建中,可以通过getBean()方法获取到bean,目的是用来检测循环依赖。

3. bean的实例化

实现方法:getObjectForBeanInstance(sharedInstance, name, beanName, null);
返回值:真正想要返回的bean
方法说明:从缓存中或者createBean()获取的都是bean的原始状态,此方法就是对bean进行实例化。需要强调的是,最原始的bean并不一定是我们真正想要的bean。例如,像要factory-method方法返回的bean.

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

		// 若name传递的是如“&student”(以&为前缀)
		if (BeanFactoryUtils.isFactoryDereference(name)) {
			if (beanInstance instanceof NullBean) {
				return beanInstance;
			}
			//该bean不是FactoryBean,抛出异常
			if (!(beanInstance instanceof FactoryBean)) {
				throw new BeanIsNotAFactoryException(transformedBeanName(name), beanInstance.getClass());
			}
		}

		// 如果beanInstance不是FactoryBean,是一个普通的Bean,直接返回
		if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {
			return beanInstance;
		}

		Object object = null;
		if (mbd == null) {
			//根据beanName从缓存中加载bean,注意此处的beanName是包含‘&’符
			object = getCachedObjectForFactoryBean(beanName);
		}
		if (object == null) {
			//到这里已经明确知道beanInstance是FactoryBean类型了
			// 从工厂中返回bean实例
			FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
			// 判断已加载的类中是否定义beanname
			if (mbd == null && containsBeanDefinition(beanName)) {
				//如果对应的bean是子bean的话,则合并父类的相关属性
				mbd = getMergedLocalBeanDefinition(beanName);
			}
			//是否是用户生成的:判断是用户生成还是应用程序生成
			boolean synthetic = (mbd != null && mbd.isSynthetic());
			object = getObjectFromFactoryBean(factory, beanName, !synthetic);
		}
		return object;
	}
  • getCachedObjectForFactoryBean(beanName); 获取bean

FactoryBeanRegistrySupport.java

/** FactoryBean 创建的单例对象的缓存: FactoryBean name --> object */
private final Map<String, Object> factoryBeanObjectCache = new ConcurrentHashMap<>(16);
protected Object getCachedObjectForFactoryBean(String beanName) {
		return this.factoryBeanObjectCache.get(beanName);
	}
  • getObjectFromFactoryBean(factory, beanName, !synthetic);真正获取FactoryBean的bean
protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {
		if (factory.isSingleton() && containsSingleton(beanName)) {
			synchronized (getSingletonMutex()) {
				// 从缓存中获取,factoryBeanObjectCache存放<FactoryBean名称,Object>
				Object object = this.factoryBeanObjectCache.get(beanName);
				if (object == null) {
					// 缓存中获取不到,从factory中获取
					object = doGetObjectFromFactoryBean(factory, beanName);
					// 有可能当执行doGetObjectFromFactoryBean函数时,Bean正在创建,所以此时再获取一下
					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实例的代码在doGetObjectFromFactoryBean(factory, beanName);方法中,我们继续追踪到此方法:

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((PrivilegedExceptionAction<Object>) factory::getObject, acc);
				}
				catch (PrivilegedActionException pae) {
					throw pae.getException();
				}
			}
			else {
				//getObject()方法在实现FactoryBean接口时实现的
				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;
	}

上面这么多的代码其实真正逻辑没有几行,在doGetObjectFromFactoryBean方法中我们终于看到了factory.getObject();创建FactoryBean实例的代码。这一逻辑到此也结束了。

4 . 原型模式的依赖检查

说明:只有在单例情况下才会尝试解决循环依赖。

扫描二维码关注公众号,回复: 8885804 查看本文章
5. 检测parentBeanFactory()父工厂
7. 寻找依赖

说明:因为bean的初始化过程中很可能用到某些属性,而这些属性很可能是动态配置的。所以要先加载依赖的bean.

8.根据不同的scope进行bean的创建

scope的类型:基本作用域(singleton、prototype),Web 作用域(reqeust、session、globalsession),自定义作用域。
说明:从doGetBean()方法中知道对不同的scope,创建bean的逻辑都封装在createBean()方法中,下面就去看一看这个方法。
这里太长了,会专门也一篇文章spring源码:bean的创建

9. 类型转换

把bean转换成参数requiredType类型的。

发布了73 篇原创文章 · 获赞 36 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/jiang18238032891/article/details/101519784