Bean's Spring Ioc of load (a)

Foreword

In the previous article, we analyzed the initialization process Ioc of Spring, in fact, it is to beanNameand BeanDefinitionregistered to DefaultListableBeanFactorythe map.
After completing the registration of the bean, refresh()also called a number of ways post-processor, which has a method finishBeanFactoryInitialization()that read the comment above Instantiateall remaining(non-lazy-init)singletons, means that the non-delayed loading of the class is instantiated in this step, finish loading the class.
After which we use to context.getBean ( "beanName") method, if the corresponding non-bean lazy loading, can then be directly carried out using delayed loading bean above steps you need to load classes, finished loading to use.

We then analyze the bean instantiation of Ioc:

A, getBean

When we call display or implicitly BeanFactory#getBean(String name)when the method is triggered loaded Bean stage. code show as below:

// AbstractBeanFactory.java

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

Internal call doGetBean(String name, final Class<T> requiredType, Object[] args, boolean typeCheckOnly)method, which method accepts four parameters:

  • name: To obtain the name of Bean

  • requiredType: To get the type of bean

  • args: arguments passed when creating Bean. This parameter is limited to use when creating the Bean.

  • typeCheckOnly: whether the type checking.

Two, doGetBean

//真正实现向IOC容器获取Bean的功能,也是触发依赖注入功能的地方
	protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
			@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {

		//根据指定的名称获取被管理Bean的名称,剥离指定名称中对容器的相关依赖
		// 如果指定的是别名,将别名转换为规范的Bean名称
<1>		final String beanName = transformedBeanName(name);
		Object bean;

		// Eagerly check singleton cache for manually registered singletons.
		// 从缓存中获取已被创建过的单例Bean
<2>		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的工厂
			//     FactoryBean是创建创建对象的工厂Bean,两者之间有区别

			//获取给定Bean的实例对象,该对象要么是 bean 实例本身,要么就是 FactoryBean 创建的 Bean 对象
			//(为什么要再次获取呢,因为上面获取的sharedInstance不一定是完整的)
<3>			bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
		}

		else {
			// Fail if we're already creating this bean instance:
			// We're assumably within a circular reference.
			// 因为 Spring 只解决单例模式下的循环依赖,在原型模式下如果存在循环依赖则会抛出异常。
<4>			if (isPrototypeCurrentlyInCreation(beanName)) {
				throw new BeanCurrentlyInCreationException(beanName);
			}

			// Check if bean definition exists in this factory.
			//对IOC容器中是否存在指定名称的BeanDefinition进行检查,首先检查是否
			//能在当前的BeanFactory中获取的所需要的Bean,如果不能则委托当前容器
			//的父级容器去查找,如果还是找不到则沿着容器的继承体系向父级容器查找
			BeanFactory parentBeanFactory = getParentBeanFactory();
			//当前容器的父级容器存在,且当前容器中不存在指定名称的Bean
			if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
				// Not found -> check parent.
				//解析指定Bean名称的原始名称
				String nameToLookup = originalBeanName(name);
				// 若为 AbstractBeanFactory 类型,委托父类处理
				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 {
					// No args -> delegate to standard getBean method.
					//委派父级容器根据指定名称和类型查找
					return parentBeanFactory.getBean(nameToLookup, requiredType);
				}
			}

			// 创建的Bean是否需要进行类型验证,一般不需要
<5>			if (!typeCheckOnly) {
				//向容器标记指定的Bean已经被创建
				markBeanAsCreated(beanName);
			}

			try {
				//从容器中获取 beanName 相应的 GenericBeanDefinition 对象,并将其转换为 RootBeanDefinition 对象
				// 主要解决Bean继承时子类合并父类公共属性问题
<6>				final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
				// 检查给定的合并的 BeanDefinition (是否为抽象类)
				checkMergedBeanDefinition(mbd, beanName, args);

				// Guarantee initialization of beans that the current bean depends on.
				// 处理所依赖的 bean @DependsOn()
				// 获取当前Bean所有依赖Bean的名称
<7>				String[] dependsOn = mbd.getDependsOn();
				//如果有依赖
				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 + "'");
						}
						//没有,则先注册依赖的bean
						registerDependentBean(dep, beanName);
						//递归调用getBean(),先生成依赖的bean
						getBean(dep);
					}
				}

				// Create bean instance.
				//创建单例Bean
<8>				if (mbd.isSingleton()) {
					//这里使用了一个匿名内部类,创建Bean实例对象,并且注册给所依赖的对象
					sharedInstance = getSingleton(beanName, () -> {
						try {
							//创建一个指定Bean实例对象,如果有父级继承,则合并子类和父类的定义
							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.
							//显式地从容器单例模式Bean缓存中清除实例对象
							destroySingleton(beanName);
							throw ex;
						}
					});
					//获取给定Bean的实例对象
					bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
				}

				//创建多例Bean
				else if (mbd.isPrototype()) {
					//原型模式(Prototype)是每次都会创建一个新的对象
					Object prototypeInstance = null;
					try {
						//加载前置处理,默认的功能是注册当前创建的原型对象
						beforePrototypeCreation(beanName);
						//创建指定Bean对象实例
						prototypeInstance = createBean(beanName, mbd, args);
					}
					finally {
						//加载后置处理,默认的功能告诉IOC容器指定Bean的原型对象不再创建
						afterPrototypeCreation(beanName);
					}
					//获取给定Bean的实例对象
					bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
				}

				//要创建的Bean既不是Singleton也不是Prototype
				//如:request、session、application等生命周期
				else {
					String scopeName = mbd.getScope();
					final Scope scope = this.scopes.get(scopeName);
					//Bean定义资源中没有配置生命周期范围,则Bean定义不合法
					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) {
				cleanupAfterBeanCreationFailure(beanName);
				throw ex;
			}
		}

		// Check if required type matches the type of the actual bean instance.
		//对创建的Bean实例对象进行类型检查
<9>		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;
	}
复制代码

The code is long and requires some patience, let's take a step by step analysis of the code:

  • <1> at: specific analysis, see2.1获取原始beanName

  • <2> at: specific analysis, see2.2从缓存中获取单例bean

  • <3> at: specific analysis, see2.3获取最终的bean实例对象

  • <4> at: specific analysis, see2.4原型模式依赖检查

  • <5> at: specific analysis, see2.5标记bean为已创建或即将创建

  • <6> at: specific analysis, see2.6获取BeanDefinition

  • <7> at: specific analysis, see2.7bean依赖处理

  • <8> at: specific analysis, see2.8不同作用域bean的实例化

  • <9> at: specific analysis, see2.9类型转换

2.1, to obtain the original beanName

code show as below:

final String beanName = transformedBeanName(name);
复制代码

Continue in-depth, as follows:

protected String transformedBeanName(String name) {
		return canonicalName(BeanFactoryUtils.transformedBeanName(name));
	}
复制代码

BeanFactoryUtils.transformedBeanName(name)The main method is to remove the modifier FactoryBean

//对FactoryBean的转义定义,因为如果使用bean的名字检索FactoryBean得到的对象是工厂生成的对象,
	//如果需要得到工厂本身,需要转义
	String FACTORY_BEAN_PREFIX = "&";

public static String transformedBeanName(String name) {
		Assert.notNull(name, "'name' must not be null");
		String beanName = name;
		while (beanName.startsWith(BeanFactory.FACTORY_BEAN_PREFIX)) {
			beanName = beanName.substring(BeanFactory.FACTORY_BEAN_PREFIX.length());
		}
		return beanName;
	}
复制代码

ps: If a factoryBeanname is "student", acquired factoryBeanwhen Bean created, use getBean("student"), access factoryBeantime itself, using the getBean("&student")
then-depth, the final code is as follows:

/** Map from alias to canonical name */
	private final Map<String, String> aliasMap = new ConcurrentHashMap<>(16);


//循环处理,从aliasMap中根据aliasName获取真实beanName,直到获取到的真实beanName为null
	public String canonicalName(String name) {
		String canonicalName = name;
		// Handle aliasing...
		String resolvedName;
		do {
			resolvedName = this.aliasMap.get(canonicalName);
			if (resolvedName != null) {
				canonicalName = resolvedName;
			}
		}
		while (resolvedName != null);
		return canonicalName;
	}
复制代码

The main loop is a process of acquiring beanName, e.g., alias point A to B bean B every name is returned, if the alias points A B alias, alias names for the point B of the bean C, C is returned

2.2, obtaining from the cache singleton bean

Spring bean to create the Singleton pattern only once. Follow-up, if the reacquisition Bean, it is available directly from the cache in a single embodiment, the process is embodied in #getSingleton (String beanName) method. code show as below:

	/** Cache of singleton objects: bean name --> bean instance */
	//单例bean的缓存
	private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);

	/** Cache of singleton factories: bean name --> ObjectFactory */
	//单例对象工厂缓存
	private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);

	/** Cache of early singleton objects: bean name --> bean instance */
	//预加载单例bean缓存
	//存放的 bean 不一定是完整的
	private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);

//对于单例模式的Bean整个IOC容器中只创建一次,不需要重复创建
	@Nullable
	protected Object getSingleton(String beanName, boolean allowEarlyReference) {
		//从单例缓存中获取单例bean
		Object singletonObject = this.singletonObjects.get(beanName);
		//如果缓存中没有 并且 该bean正在创建
		if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
			synchronized (this.singletonObjects) {
				singletonObject = this.earlySingletonObjects.get(beanName);
				// earlySingletonObjects 中没有,且允许提前创建
				if (singletonObject == null && allowEarlyReference) {
					//从缓存中获取 ObjectFactory
					ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
					if (singletonFactory != null) {
						//从单例工厂中获取bean
						singletonObject = singletonFactory.getObject();
						//存入early
						this.earlySingletonObjects.put(beanName, singletonObject);
						this.singletonFactories.remove(beanName);
					}
				}
			}
		}
		return singletonObject;
	}
复制代码

This code is very simple, the process is as follows:

  • The first step, from singletonObjectsobtaining Bean object

  • The second step, if you can not get in and Bean are creating, from earlySingletonObjectsacquiring objects Bean

  • The third step, if not get ahead and allow creation, from singletonFactoriesacquiring FactoryBean

  • The fourth step, if not null, then by FactoryBean.getObject()acquiring Bean, then add it to earlySingletonObjectsand from singletonFactoriesdeleted, the two are mutually exclusive, mainly used to solve the problem of circular dependencies

  • Conclusion is: in order to get from the three Map, fail to get it removed a Map

2.2.1、isSingletonCurrentlyInCreation

In the above code another important method isSingletonCurrentlyInCreation(beanName), as follows:

private final Set<String> singletonsCurrentlyInCreation =
			Collections.newSetFromMap(new ConcurrentHashMap<>(16));
	
public boolean isSingletonCurrentlyInCreation(String beanName) {
		return this.singletonsCurrentlyInCreation.contains(beanName);
	}
复制代码

This method is used to determine whether the current Bean is created, we see a Map, we can guess, there should be BeanName a place in the creation of Bean, we will being created to put into the Map. Then we will be specific.

2.2.2、getObjectForBeanInstance

From when we getSingleton(beanName)get the bean object will then call the getObjectForBeanInstance()method to get the final Bean instance.

  • Why get here once again Bean it before obviously have got it?

  • Because we get the bean from the cache is the most primitive of Bean, is not necessarily the final we wanted Bean

  • How to do it? Call #getObjectForBeanInstance (...) method, processing, define the method of obtaining a given object Bean instance, the object is either bean instance itself, or is FactoryBean Bean object created.

Look at the code:

//获取给定Bean的实例对象,主要是完成FactoryBean的相关处理
	protected Object getObjectForBeanInstance(
			Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {

		// Don't let calling code try to dereference the factory if the bean isn't a factory.
		//容器已经得到了Bean实例对象,这个实例对象可能是一个普通的Bean,
		//也可能是一个工厂Bean,如果是一个工厂Bean,则使用它创建一个Bean实例对象,
		//如果调用本身就想获得一个容器的引用,则指定返回这个工厂Bean实例对象

		//若为工厂类引用(name 以 & 开头) 且 Bean实例也不是 FactoryBean
		if (BeanFactoryUtils.isFactoryDereference(name) && !(beanInstance instanceof FactoryBean)) {
			//抛出异常
			throw new BeanIsNotAFactoryException(transformedBeanName(name), beanInstance.getClass());
		}

		// Now we have the bean instance, which may be a normal bean or a FactoryBean.
		
		//如果类型不是FactoryBean,直接返回
		if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {
			return beanInstance;
		}

		Object object = null;
		//若 BeanDefinition 为 null,则从缓存中加载 Bean 对象
		if (mbd == null) {
			//从Bean工厂缓存中获取给定名称的Bean实例对象
			object = getCachedObjectForFactoryBean(beanName);
		}

		// 若 object 依然为空,则可以确认,beanInstance 一定是 FactoryBean 。从而,使用 FactoryBean 获得 Bean 对象
		if (object == null) {
			// Return bean instance from factory.
			FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
			// Caches object obtained from FactoryBean if it is a singleton.
			// 检测是否定义 beanName
			if (mbd == null && containsBeanDefinition(beanName)) {
				//从容器中获取指定名称的Bean定义,如果继承基类,则合并基类相关属性
				mbd = getMergedLocalBeanDefinition(beanName);
			}
			//如果从容器得到Bean定义信息,并且Bean定义信息不是虚构的,
			//则让工厂Bean生产Bean实例对象
			boolean synthetic = (mbd != null && mbd.isSynthetic());
			//调用FactoryBeanRegistrySupport类的getObjectFromFactoryBean方法,
			//实现工厂Bean生产Bean对象实例的过程
			object = getObjectFromFactoryBean(factory, beanName, !synthetic);
		}
		return object;
	}
复制代码

First look at the method of process:

  • 1, type checking to determine whether the FactoryBean

  • 2, non-FactoryBean not treated

  • 3, the bean conversion

  • 4, the processing FactoryBean Type: getObjectFromFactoryBean to delegate processing method.

We look directly at step 3, come here, this description must be bean FactoryBeantypes, and then obtain the corresponding beanName BeanDefinition Ioc from the container, if not null, and is not abstract, for calling getObjectFromFactoryBeanmethod to obtain bean Example

As can be seen from this, getObjectForBeanInstance(Object beanInstance, String name, String beanName,RootBeanDefinition mbd)the method is divided into two situations:

  • First, when an object instance of the 非 FactoryBeantype, directly back to the given instance of the object Bean beanInstance.

  • Second, when the object instance FactoryBeantype, from FactoryBean (beanInstance), gets Bean instance object.

2.2.3、getObjectFromFactoryBean

We then look at the second case:

//Bean工厂生产Bean实例对象
	protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {
		//为单例模式且缓存中存在
		if (factory.isSingleton() && containsSingleton(beanName)) {
			//多线程同步,以防止数据不一致
1.1			synchronized (getSingletonMutex()) {
				//从缓存中获取指定的 factoryBean
1.2				Object object = this.factoryBeanObjectCache.get(beanName);
				if (object == null) {
					// 为空,则从 FactoryBean 中获取对象
					object = doGetObjectFromFactoryBean(factory, beanName);
					// Only post-process and store if not put there already during getObject() call above
					// (e.g. because of circular reference processing triggered by custom getBean calls)
					Object alreadyThere = this.factoryBeanObjectCache.get(beanName);
					if (alreadyThere != null) {
						object = alreadyThere;
					}
					else {
1.3						if (shouldPostProcess) {
							try {
								// 对从 FactoryBean 获取的对象进行后处理
								// 生成的对象将暴露给 bean 引用
								object = postProcessObjectFromFactoryBean(object, beanName);
							}
							catch (Throwable ex) {
								throw new BeanCreationException(beanName,
										"Post-processing of FactoryBean's singleton object failed", ex);
							}
						}
						//将生产的实例对象添加到Bean工厂缓存中
1.4						this.factoryBeanObjectCache.put(beanName, object);
					}
				}
				return object;
			}
		}
		// 为空,则从 FactoryBean 中获取对象
2		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;
		}
	}
复制代码
  • 1, and determines whether singleton exists in the cache, if present, go down along the 1.1, does not exist, go to Scheme 2

  • 1.1, sync lock, lock that singletonObjects, lock and other singleton as the only global guarantee

  • 1.2, from the cache factoryBeanObjectCacheGet Bean instance if the acquisition is less than, the call doGetObjectFromFactoryBean()method to get the actual call is the last factory.getObject()method

  • 1.3, if necessary subsequent processing (shouldPostProcess = true), then the next processing postProcessObjectFromFactoryBean()method, an object instance of Bean FactoryBean acquired from the post-process. The default implementation is returned directly target object, without any treatment. code show as below:

protected Object postProcessObjectFromFactoryBean(Object object, String beanName) throws BeansException {
		return object;
	}
复制代码

However, subclasses can override, for example, after the application processor and the like.

  • 1.4, was added to the cache factoryBeanObjectCache
  • 2, if the cache does not exist, the same call to doGetObjectFromFactoryBean()get the bean instance

Summary:
here, doGetBean () method 2.2从缓存中获取单例beanand 2.3获取最终的bean实例对象we have analyzed over, the next article we step back and then analyzed.

Guess you like

Origin juejin.im/post/5d6dd278f265da03e921e6fd