IoC依赖注入过程

前端之家收集整理的这篇文章主要介绍了IoC依赖注入过程前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

上一节是Ioc容器初始化过程,初始化过程基本就是做了一件大事:在IoC容器中构建出了BeanDefinition数据结构映射.构建出数据结构映射后,却没有看到依赖注入,下面就看看是怎么依赖注入的.

首先,注意到依赖注入的过程是用户第一次向IoC容器索要Bean时触发的,在基本的IoC容器接口beanfactory中,有一个getBean的接口定义,这个接口的实现就是触发依赖注入发生的地方.当然也有例外,也就是我们可以在BeanDefinition信息中通过控制lazy-init属性来控制容器完成对Bean的预实例化。这个预实例化实际上也是一个完成依赖注入的过程,但它是在初始化的过程中完成的,

以DefaultListablebeanfactory容器为例,简短的描述下.

整个过程的图示为:

从图上看,getBean是依赖注入的起点,之后会调用createBean,下面从DefaultListablebeanfactory的基类Abstractbeanfactory中的getBean的实现来了解这个过程。

DefaultListablebeanfactory容器的getBean整个过程步骤如下:

1.从缓存获取当前beanName,看当前类型的bean是否已经被创建过,如果没有创建过,就创建一个bean。

2.如果创建过,就从当前beanfactory获取bean,如果当前工厂取不到,就从双亲beanfactory中取,一直进行迭代查找。

3.如果是需要标记,并且还没有创建过,就进行标记

4.获取当前bean的所有依赖的bean,需要对当依赖的bean进行getBean递归调用,知道依赖的bean都创建为止。

5.根据protype调用createBean创建单例,原型模式实例,或者根据自定义scope创建实例

6.对创建的bean进行类型检查,如果没问题就返回.

代码如下:

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

		final String beanName = transformedBeanName(name);
		Object bean;

		// Eagerly check singleton cache for manually registered singletons.
		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 + "'");
				}
			}
			bean = getObjectForBeanInstance(sharedInstance,name,beanName,null);
		}

		else {
			// Fail if we're already creating this bean instance:
			// We're assumably within a circular reference.
			if (isPrototypeCurrentlyInCreation(beanName)) {
				throw new BeanCurrentlyInCreationException(beanName);
			}

			// Check if bean definition exists in this factory.
			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);
				}
			}

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

			try {
				final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
				checkMergedBeanDefinition(mbd,args);

				// Guarantee initialization of beans that the current bean depends on.
				String[] dependsOn = mbd.getDependsOn();
				if (dependsOn != null) {
					for (String dependsOnBean : dependsOn) {
						if (isDependent(beanName,dependsOnBean)) {
							throw new BeanCreationException(mbd.getResourceDescription(),"Circular depends-on relationship between '" + beanName + "' and '" + dependsOnBean + "'");
						}
						registerDependentBean(dependsOnBean,beanName);
						getBean(dependsOnBean);
					}
				}

				// Create bean instance.
				if (mbd.isSingleton()) {
					sharedInstance = getSingleton(beanName,new ObjectFactory<Object>() {
						@Override
						public Object getObject() throws BeansException {
							try {
								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 = getObjectForBeanInstance(sharedInstance,mbd);
				}

				else if (mbd.isPrototype()) {
					// It's a prototype -> create a new instance.
					Object prototypeInstance = null;
					try {
						beforePrototypeCreation(beanName);
						prototypeInstance = createBean(beanName,args);
					}
					finally {
						afterPrototypeCreation(beanName);
					}
					bean = getObjectForBeanInstance(prototypeInstance,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,args);
								}
								finally {
									afterPrototypeCreation(beanName);
								}
							}
						});
						bean = getObjectForBeanInstance(scopedInstance,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;
			}
		}

这个过程简要概括为,getBean是依赖注入的起点,之后会调用create-Bean,下面通过createBean代码来了解这个实现过程。在这个过程中,Bean对象会依据BeanDefinition定义的要求生成。在AbstractAutowireCapablebeanfactory中实现了这个createBean,createBean不但生成了需要的Bean,还对Bean初始化进行了处理.注入过程如下图:

createBean方法如下:

/**
 * Central method of this class: creates a bean instance,* populates the bean instance,applies post-processors,etc.
 * @see #doCreateBean
*/
protected Object createBean(String beanName,RootBeanDefinition mbd,Object[] args) throws BeanCreationException {
		if (logger.isDebugEnabled()) {
			logger.debug("Creating instance of bean '" + beanName + "'");
		}
		RootBeanDefinition mbdToUse = mbd;

		// Make sure bean class is actually resolved at this point,and
		// clone the bean definition in case of a dynamically resolved Class
		// which cannot be stored in the shared merged bean definition.
     //确认需要创建的Bean实例的类是否可以实例化
		Class<?> resolvedClass = resolveBeanClass(mbd,beanName);
		if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
			mbdToUse = new RootBeanDefinition(mbd);
			mbdToUse.setBeanClass(resolvedClass);
		}

		// Prepare method overrides.
		try {
			mbdToUse.prepareMethodOverrides();
		}
		catch (BeanDefinitionValidationException ex) {
			throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),"Validation of method overrides Failed",ex);
		}

		try {
			// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
       //如果bean配置了PostProcessor 那么会返回proxy
			Object bean = resolveBeforeInstantiation(beanName,mbdToUse);
			if (bean != null) {
				return bean;
			}
		}
		catch (Throwable ex) {
			throw new BeanCreationException(mbdToUse.getResourceDescription(),"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;
	}

从上面接着看doCreateBean方法

/**
 * Actually create the specified bean. Pre-creation processing has already happened
 * at this point,e.g. checking {@code postProcessBeforeInstantiation} callbacks.
 * <p>Differentiates between default bean instantiation,use of a
 * factory method,and autowiring a constructor.
 * @param beanName the name of the bean
 * @param mbd the merged bean definition for the bean
 * @param args explicit arguments to use for constructor or factory method invocation
 * @return a new instance of the bean
 * @throws BeanCreationException if the bean could not be created
 * @see #instantiateBean
 * @see #instantiateUsingFactoryMethod
 * @see #autowireConstructor
*/
	protected Object doCreateBean(final String beanName,final RootBeanDefinition mbd,final Object[] args) {
		// Instantiate the bean.
		BeanWrapper instanceWrapper = null;
        //如果是单例,仙踪缓存中把同名bean移除
		if (mbd.isSingleton()) {
			instanceWrapper = this.factorybeanInstanceCache.remove(beanName);
		}
     //createBeanInstance创建实例
		if (instanceWrapper == null) {
			instanceWrapper = createBeanInstance(beanName,args);
		}
		final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null);
		Class<?> beanType = (instanceWrapper != null ? instanceWrapper.getWrappedClass() : null);

		// Allow post-processors to modify the merged bean definition.
		synchronized (mbd.postProcessingLock) {
			if (!mbd.postProcessed) {
				applyMergedBeanDefinitionPostProcessors(mbd,beanType,beanName);
				mbd.postProcessed = true;
			}
		}

		// Eagerly cache singletons to be able to resolve circular references
		// even when triggered by lifecycle interfaces like beanfactoryAware.
		boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
				isSingletonCurrentlyInCreation(beanName));
		if (earlySingletonExposure) {
			if (logger.isDebugEnabled()) {
				logger.debug("Eagerly caching bean '" + beanName +
						"' to allow for resolving potential circular references");
			}
			addSingletonFactory(beanName,new ObjectFactory<Object>() {
				@Override
				public Object getObject() throws BeansException {
					return getEarlyBeanReference(beanName,bean);
				}
			});
		}

		// Initialize the bean instance.
		Object exposedObject = bean;
		try {
        //开始依赖注入
			populateBean(beanName,instanceWrapper);
			if (exposedObject != null) {
				exposedObject = initializeBean(beanName,exposedObject,mbd);
			}
		}
		catch (Throwable ex) {
			if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
				throw (BeanCreationException) ex;
			}
			else {
				throw new BeanCreationException(mbd.getResourceDescription(),"Initialization of bean Failed",ex);
			}
		}

		if (earlySingletonExposure) {
			Object earlySingletonReference = getSingleton(beanName,false);
			if (earlySingletonReference != null) {
				if (exposedObject == bean) {
					exposedObject = earlySingletonReference;
				}
				else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
					String[] dependentBeans = getDependentBeans(beanName);
					Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
					for (String dependentBean : dependentBeans) {
						if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
							actualDependentBeans.add(dependentBean);
						}
					}
					if (!actualDependentBeans.isEmpty()) {
						throw new BeanCurrentlyInCreationException(beanName,"Bean with name '" + beanName + "' has been injected into other beans [" +
								StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
								"] in its raw version as part of a circular reference,but has eventually been " +
								"wrapped. This means that said other beans do not use the final version of the " +
								"bean. This is often the result of over-eager type matching - consider using " +
								"'getBeanNamesOfType' with the 'allowEagerInit' flag turned off,for example.");
					}
				}
			}
		}

		// Register bean as disposable.
		try {
			registerDisposableBeanIfNecessary(beanName,bean,mbd);
		}
		catch (BeanDefinitionValidationException ex) {
			throw new BeanCreationException(mbd.getResourceDescription(),"Invalid destruction signature",ex);
		}

		return exposedObject;
	}

从doCreateBean方法可以看出,与依赖注入关系特别密切的方法有createBeanInstance和populateBean,下面分别介绍这两个方法。在createBeanInstance中生成了Bean所包含的Java对象,这个对象的生成有很多种不同的方式,可以通过工厂方法生成,也可以通过容器的autowire特性生成,这些生成方式都是由相关的BeanDefinition来指定的。

createBeanInstance方法如下:

/**
 * Create a new instance for the specified bean,using an appropriate instantiation strategy:
 * factory method,constructor autowiring,or simple instantiation.
 * @param beanName the name of the bean
 * @param mbd the bean definition for the bean
 * @param args explicit arguments to use for constructor or factory method invocation
 * @return BeanWrapper for the new instance
 * @see #instantiateUsingFactoryMethod
 * @see #autowireConstructor
 * @see #instantiateBean
*/
	protected BeanWrapper createBeanInstance(String beanName,Object[] args) {
		// Make sure bean class is actually resolved at this point.
		Class<?> beanClass = resolveBeanClass(mbd,beanName);

		if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {
			throw new BeanCreationException(mbd.getResourceDescription(),"Bean class isn't public,and non-public access not allowed: " + beanClass.getName());
		}
     //使用工厂方法对bean进行实例化
		if (mbd.getFactoryMethodName() != null)  {
			return instantiateUsingFactoryMethod(beanName,args);
		}

		// Shortcut when re-creating the same bean...
		boolean resolved = false;
		boolean autowireNecessary = false;
		if (args == null) {
			synchronized (mbd.constructorArgumentLock) {
				if (mbd.resolvedConstructorOrFactoryMethod != null) {
					resolved = true;
					autowireNecessary = mbd.constructorArgumentsResolved;
				}
			}
		}
		if (resolved) {
			if (autowireNecessary) {
				return autowireConstructor(beanName,null,null);
			}
			else {
				return instantiateBean(beanName,mbd);
			}
		}

		// Need to determine the constructor...
     //使用构造函数进行实例化,前提是有构造函数
		Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass,beanName);
		if (ctors != null ||
				mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR ||
				mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args))  {
			return autowireConstructor(beanName,ctors,args);
		}

		// No special handling: simply use no-arg constructor.
     //使用默认的构造方法
		return instantiateBean(beanName,mbd);
	}

populateBean方法如下:

/**
 * Populate the bean instance in the given BeanWrapper with the property values
 * from the bean definition.
 * @param beanName the name of the bean
 * @param mbd the bean definition for the bean
 * @param bw BeanWrapper with bean instance
*/
	protected void populateBean(String beanName,BeanWrapper bw) {
		PropertyValues pvs = mbd.getPropertyValues();

		if (bw == null) {
			if (!pvs.isEmpty()) {
				throw new BeanCreationException(
						mbd.getResourceDescription(),"Cannot apply property values to null instance");
			}
			else {
				// Skip property population phase for null instance.
				return;
			}
		}

		// Give any InstantiationAwareBeanPostProcessors the opportunity to modify the
		// state of the bean before properties are set. This can be used,for example,// to support styles of field injection.
		boolean continueWithPropertyPopulation = true;

		if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
			for (BeanPostProcessor bp : getBeanPostProcessors()) {
				if (bp instanceof InstantiationAwareBeanPostProcessor) {
					InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
					if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(),beanName)) {
						continueWithPropertyPopulation = false;
						break;
					}
				}
			}
		}

		if (!continueWithPropertyPopulation) {
			return;
		}
     //开始处理autowire类型的注入,支持按bean的名字和类型
		if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME ||
				mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
			MutablePropertyValues newPvs = new MutablePropertyValues(pvs);

			// Add property values based on autowire by name if applicable.
			if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) {
				autowireByName(beanName,bw,newPvs);
			}

			// Add property values based on autowire by type if applicable.
			if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
				autowireByType(beanName,newPvs);
			}

			pvs = newPvs;
		}

		boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
		boolean needsDepCheck = (mbd.getDependencyCheck() != RootBeanDefinition.DEPENDENCY_CHECK_NONE);

		if (hasInstAwareBpps || needsDepCheck) {
			PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw,mbd.allowCaching);
			if (hasInstAwareBpps) {
				for (BeanPostProcessor bp : getBeanPostProcessors()) {
					if (bp instanceof InstantiationAwareBeanPostProcessor) {
						InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
						pvs = ibp.postProcessPropertyValues(pvs,filteredPds,bw.getWrappedInstance(),beanName);
						if (pvs == null) {
							return;
						}
					}
				}
			}
			if (needsDepCheck) {
				checkDependencies(beanName,pvs);
			}
		}
     //对bean的属性进行注入
		applyPropertyValues(beanName,pvs);
	}

注入过程的其他细节就不再赘述了.

在Bean的创建和对象依赖注入的过程中,需要依据载入的BeanDefinition中的信息来递归地完成依赖注入。从上面的几个递归过程中可以看到,这些递归都是以getBean为入口的。一个递归是在上下文体系中查找需要的Bean和创建Bean的递归调用;另一个递归是在依赖注入时,通过递归调用容器的getBean方法,得到当前Bean的依赖Bean,同时也触发对依赖Bean的创建和注入。在对Bean的属性进行依赖注入时,解析的过程也是一个递归的过程。这样,根据依赖关系,一层一层地完成Bean的创建和注入,直到最后完成当前Bean的创建。有了这个顶层Bean的创建和对它的属性依赖注入的完成,意味着和当前Bean相关的整个依赖链的注入也完成了。

在Bean创建和依赖注入完成以后,在IoC容器中建立起一系列依靠依赖关系联系起来的Bean,这个Bean已经不是简单的Java对象了。该Bean系列以及Bean之间的依赖关系建立完成以后,通过IoC容器的相关接口方法,就可以非常方便地供上层应用使用了。继续以水桶为例,到这里,我们不但找到了水源,而且成功地把水装到了水桶中,同时对水桶里的水完成了一系列的处理,比如消毒、煮沸……尽管还是水,但经过一系列的处理以后,这些水已经是开水了,可以直接饮用了。

参考:

1.https://github.com/spring-projects/spring-framework.

2.<<Spring技术内幕>>

猜你在找的设计模式相关文章