Spring IoC容器设计与实现——容器相关特性的实现(lazy-init属性和预实例化、FactoryBean、BeanPostProcessor、autowire、Bean依赖检查)

ApplicationContext和Bean的初始化及销毁

对于BeanFactory,特别是ApplicationContext,容器自身也有一个初始化及销毁关闭的过程。

在这里插入图片描述
ApplicationContext启动的过程是在AbstractApplicationContext中实现的,在这之前需要一些准备工作prepareBeanFactory()方法实现,这个方法中为容器配置了ClassLoader、PropertyEditor和BeanPostProcessor等,为容器启动做好了必要的准备工作。

/**
	 * 配置工厂的标准上下文特征,例如上下文的ClassLoader和后处理器。
	 * Configure the factory's standard context characteristics,
	 * such as the context's ClassLoader and post-processors.
	 * @param beanFactory the BeanFactory to configure
	 */
	protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
		// Tell the internal bean factory to use the context's class loader etc.
		beanFactory.setBeanClassLoader(getClassLoader());
		if (!shouldIgnoreSpel) {
			beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
		}
		beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));

		// Configure the bean factory with context callbacks.
		beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
		beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
		beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
		beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
		beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
		beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
		beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
		beanFactory.ignoreDependencyInterface(ApplicationStartup.class);

		beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
		beanFactory.registerResolvableDependency(ResourceLoader.class, this);
		beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
		beanFactory.registerResolvableDependency(ApplicationContext.class, this);

		// Register early post-processor for detecting inner beans as ApplicationListeners.
		beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));

		// Detect a LoadTimeWeaver and prepare for weaving, if found.
		if (!IN_NATIVE_IMAGE && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
			beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
			// Set a temporary ClassLoader for type matching.
			beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
		}

		// Register default environment beans.
		if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
			beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
		}
		if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
			beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
		}
		if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
			beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
		}
		if (!beanFactory.containsLocalBean(APPLICATION_STARTUP_BEAN_NAME)) {
			beanFactory.registerSingleton(APPLICATION_STARTUP_BEAN_NAME, getApplicationStartup());
		}
	}

同样在容器要关闭时,也需要完成一系列工作,这些工作在doClose方法中完成,这个方法中先发出容器关闭的信息,然后将Bean逐个关闭,最后关闭容器自身。

protected void doClose() {
		// Check whether an actual close attempt is necessary...
		if (this.active.get() && this.closed.compareAndSet(false, true)) {
			if (logger.isDebugEnabled()) {
				logger.debug("Closing " + this);
			}

			if (!IN_NATIVE_IMAGE) {
				LiveBeansView.unregisterApplicationContext(this);
			}

			try {
				// Publish shutdown event.
				publishEvent(new ContextClosedEvent(this));
			}
			catch (Throwable ex) {
				logger.warn("Exception thrown from ApplicationListener handling ContextClosedEvent", ex);
			}

			// Stop all Lifecycle beans, to avoid delays during individual destruction.
			if (this.lifecycleProcessor != null) {
				try {
					this.lifecycleProcessor.onClose();
				}
				catch (Throwable ex) {
					logger.warn("Exception thrown from LifecycleProcessor on context close", ex);
				}
			}

			// Destroy all cached singletons in the context's BeanFactory.
			// 销毁上下文的BeanFactory中所有缓存的单例。
			destroyBeans();

			// Close the state of this context itself.
			// 关闭此上下文本身的状态。
			closeBeanFactory();

			// Let subclasses do some final clean-up if they wish...
			onClose();

			// Reset local application listeners to pre-refresh state.
			if (this.earlyApplicationListeners != null) {
				this.applicationListeners.clear();
				this.applicationListeners.addAll(this.earlyApplicationListeners);
			}

			// Switch to inactive.
			this.active.set(false);
		}
	}

容器的实现是通过IoC管理Bean的生命周期来实现的,Spring IoC容器在对Bean的生命周期进行管理时提供了Bean生命周期各个时间点的回调。

IoC容器中Bean的声明周期

  • Bean实例的创建;
  • 为Bean实例设置属性;
  • 调用Bean的初始化方法;
  • 应用可以通过IoC容器使用Bean;
  • 容器关闭时,调用Bean的销毁方法。
/**
	 * 初始化给定的bean实例,应用工厂回调以及init方法和bean post处理器。
	 */
	protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
		if (System.getSecurityManager() != null) {
			AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
				invokeAwareMethods(beanName, bean);
				return null;
			}, getAccessControlContext());
		}
		else {
			invokeAwareMethods(beanName, bean);
		}

		Object wrappedBean = bean;
		if (mbd == null || !mbd.isSynthetic()) {
			wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
		}

		try {
			invokeInitMethods(beanName, wrappedBean, mbd);
		}
		catch (Throwable ex) {
			throw new BeanCreationException(
					(mbd != null ? mbd.getResourceDescription() : null),
					beanName, "Invocation of init method failed", ex);
		}
		if (mbd == null || !mbd.isSynthetic()) {
			wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
		}

		return wrappedBean;
	}

在调用Bean初始化方法之前,会调用一系列aware接口实现,在invokeInitMethods方法中实现。

/**
	 * 将相关的BeanName、BeanClassLoader以及BeanFactory注入到Bean中
	 * @param beanName
	 * @param bean
	 */
	private void invokeAwareMethods(String beanName, Object bean) {
		if (bean instanceof Aware) {
			if (bean instanceof BeanNameAware) {
				((BeanNameAware) bean).setBeanName(beanName);
			}
			if (bean instanceof BeanClassLoaderAware) {
				ClassLoader bcl = getBeanClassLoader();
				if (bcl != null) {
					((BeanClassLoaderAware) bean).setBeanClassLoader(bcl);
				}
			}
			if (bean instanceof BeanFactoryAware) {
				((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
			}
		}
	}

接下来,调用Bean的初始化方法,最后还会看到判断Bean是否配置有initMethod,如果有,则通过调用invokeCustomInitMethod方法来直接调用,最终完成Bean的初始化。

	/**
	 * 在给定的bean上调用指定的自定义init方法。
	 */
	protected void invokeCustomInitMethod(String beanName, Object bean, RootBeanDefinition mbd)
			throws Throwable {

		String initMethodName = mbd.getInitMethodName();
		Assert.state(initMethodName != null, "No init method set");
		Method initMethod = (mbd.isNonPublicAccessAllowed() ?
				BeanUtils.findMethod(bean.getClass(), initMethodName) :
				ClassUtils.getMethodIfAvailable(bean.getClass(), initMethodName));

		if (initMethod == null) {
			if (mbd.isEnforceInitMethod()) {
				throw new BeanDefinitionValidationException("Could not find an init method named '" +
						initMethodName + "' on bean with name '" + beanName + "'");
			}
			else {
				if (logger.isTraceEnabled()) {
					logger.trace("No default init method named '" + initMethodName +
							"' found on bean with name '" + beanName + "'");
				}
				// Ignore non-existent default lifecycle methods.
				return;
			}
		}

		if (logger.isTraceEnabled()) {
			logger.trace("Invoking init method  '" + initMethodName + "' on bean with name '" + beanName + "'");
		}
		Method methodToInvoke = ClassUtils.getInterfaceMethodIfPossible(initMethod);
		// 得到initMethod,通过反射机制得到Method对象 直接调用在Bean定义中声明的初始化方法
		if (System.getSecurityManager() != null) {
			AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
				ReflectionUtils.makeAccessible(methodToInvoke);
				return null;
			});
			try {
				AccessController.doPrivileged((PrivilegedExceptionAction<Object>)
						() -> methodToInvoke.invoke(bean), getAccessControlContext());
			}
			catch (PrivilegedActionException pae) {
				InvocationTargetException ex = (InvocationTargetException) pae.getException();
				throw ex.getTargetException();
			}
		}
		else {
			try {
				ReflectionUtils.makeAccessible(methodToInvoke);
				methodToInvoke.invoke(bean);
			}
			catch (InvocationTargetException ex) {
				throw ex.getTargetException();
			}
		}
	}

lazy-init属性和预实例化

除了在IoC初始化过程中使用getBean()向容器索要Bean时会发生依赖注入之外,也有一种例外情况,就是用户可以通过设置Bean的lazy-init属性来控制预实例化的过程。

这个预实例化在初始化容器时完成Bean的依赖注入,虽然这种容器的使用方式会对容器初始化性能有一些影响,但却能够提高应用第一次取得Bean的性能。

初始化上下文是refresh()方法中的一个步骤,下面从lazy-init属性配置实现的角度进行分析,这个属性的处理也是refresh()的一部分。

finishBeanFactoryInitialzation的方法中,封装了对lazy-init属性的处理,实际的处理是在DefaultListableBeanFactorypreInstantiateSingletons方法中完成的,该方法对单例Bean完成预实例化。这个预实例化的完成巧妙地委托给容器来实现,如果需要预实例化那么就直接在这里采用getBean去触发依赖注入,与正常依赖注入相比,只有触发的时间和场合不同。在这里,依赖注入发生在容器执行refresh的过程中,也就是发生在IoC容器初始化的过程中,而不像一般的依赖注入一样发生在IoC容器初始化完成后。

public void refresh() throws BeansException, IllegalStateException {
		synchronized (this.startupShutdownMonitor) {
			StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");

			prepareRefresh();
			ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
			prepareBeanFactory(beanFactory);

			try {
				postProcessBeanFactory(beanFactory);

				StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
				invokeBeanFactoryPostProcessors(beanFactory);
				registerBeanPostProcessors(beanFactory);
				beanPostProcess.end();
				initMessageSource();
				initApplicationEventMulticaster();
				onRefresh();
				registerListeners();

				// Instantiate all remaining (non-lazy-init) singletons.
				// 实例化所有的非延迟化单例Bean
				finishBeanFactoryInitialization(beanFactory);
				finishRefresh();
			}
			catch (BeansException ex) {
				if (logger.isWarnEnabled()) {
					logger.warn("Exception encountered during context initialization - " +
							"cancelling refresh attempt: " + ex);
				}
				destroyBeans();
				cancelRefresh(ex);
				throw ex;
			}
			finally {
				resetCommonCaches();
				contextRefresh.end();
			}
		}
	}
	/**
	 * 完成此上下文的BeanFactory的初始化,初始化所有剩余的单例bean。
	 */
	protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
		// 如果有需要进行服务转换的Bean 则进行类型转换
		if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&
				beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
			beanFactory.setConversionService(
					beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
		}

		if (!beanFactory.hasEmbeddedValueResolver()) {
			beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));
		}

		String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
		for (String weaverAwareName : weaverAwareNames) {
			getBean(weaverAwareName);
		}

		beanFactory.setTempClassLoader(null);

		beanFactory.freezeConfiguration();


		// 调用BeanFactory的preInstantiateSingletons,这个方法由DefaultListableBeanFactory实现
		beanFactory.preInstantiateSingletons();
	}

public void preInstantiateSingletons() throws BeansException {
		if (logger.isTraceEnabled()) {
			logger.trace("Pre-instantiating singletons in " + this);
		}

		// Iterate over a copy to allow for init methods which in turn register new bean definitions.
		// While this may not be part of the regular factory bootstrap, it does otherwise work fine.
		// 遍历一个副本以允许使用init方法,这些方法依次注册新的bean定义。
		List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);

		// Trigger initialization of all non-lazy singleton beans...
		for (String beanName : beanNames) {
			RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
			// 判断BeanFactory中的BeanDefinition 是否满足:1、非抽象 2、单例Bean 3、非延迟初始化
			if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
				if (isFactoryBean(beanName)) {
					/**
					 * 和正常依赖注入过程一样,只是发生的地方不同。同样会对BeanDefinitionMap
					 * 中所有的Bean进行依赖注入,这样在初始化过程结束后,容器执行getBean得到
					 * 	的就是已经准备好的Bean不需要进行依赖注入
					 */
					Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
					if (bean instanceof FactoryBean) {
						FactoryBean<?> factory = (FactoryBean<?>) bean;
						boolean isEagerInit;
						if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
							isEagerInit = AccessController.doPrivileged(
									(PrivilegedAction<Boolean>) ((SmartFactoryBean<?>) factory)::isEagerInit,
									getAccessControlContext());
						}
						else {
							isEagerInit = (factory instanceof SmartFactoryBean &&
									((SmartFactoryBean<?>) factory).isEagerInit());
						}
						if (isEagerInit) {
							getBean(beanName);
						}
					}
				}
				else {
					getBean(beanName);
				}
			}
		}

		// Trigger post-initialization callback for all applicable beans...
		for (String beanName : beanNames) {
			Object singletonInstance = getSingleton(beanName);
			if (singletonInstance instanceof SmartInitializingSingleton) {
				StartupStep smartInitialize = this.getApplicationStartup().start("spring.beans.smart-initialize")
						.tag("beanName", beanName);
				SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
				if (System.getSecurityManager() != null) {
					AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
						smartSingleton.afterSingletonsInstantiated();
						return null;
					}, getAccessControlContext());
				}
				else {
					smartSingleton.afterSingletonsInstantiated();
				}
				smartInitialize.end();
			}
		}
	}

可以通过lazy-init属性来对整个IoC容器的初始化和依赖注入过程进行一些简单控制,这个控制是可以由容器的使用者来决定的。具体地说,可以通过在BeanDefination中设置lazy-init属性并来控制。

FactoryBean的实现

FactoryBean为应用生成需要的对象,这些对象往往是经过特殊处理的。FactoryBean的生产特性是在getBean中起作用的。

	/**
	 * 获取给定bean实例的对象,可以是bean实例本身,也可以是FactoryBean创建的对象。
	 */
	protected Object getObjectForBeanInstance(
			Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {
		// 如果这里不是对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;
		}
		// 如果是一个FactoryBean,则使用它创建一个Bean实例,除非调用者想引用它作为一个工厂
		if (!(beanInstance instanceof FactoryBean)) {
			return beanInstance;
		}

		Object object = null;
		if (mbd != null) {
			mbd.isFactoryBean = true;
		}
		else {
			// 获取FactoryBean的实例
			object = getCachedObjectForFactoryBean(beanName);
		}
		if (object == null) {
			// Return bean instance from factory.
			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());
			// 这里从FactoryBean中得到Bean
			object = getObjectFromFactoryBean(factory, beanName, !synthetic);
		}
		return object;
	}
	protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {
		if (factory.isSingleton() && containsSingleton(beanName)) {
			synchronized (getSingletonMutex()) {
				Object object = this.factoryBeanObjectCache.get(beanName);
				if (object == null) {
					object = doGetObjectFromFactoryBean(factory, beanName);
					Object alreadyThere = this.factoryBeanObjectCache.get(beanName);
					if (alreadyThere != null) {
						object = alreadyThere;
					}
					else {
						if (shouldPostProcess) {
							if (isSingletonCurrentlyInCreation(beanName)) {
								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;
		}
	}
private Object doGetObjectFromFactoryBean(FactoryBean<?> factory, 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 {
				// 这里调用factory的getObject 方法来从FactoryBean中得到Bean
				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);
		}

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

这里返回的已经是作为工厂FactoryBean生产的产品,而不是FactoryBean本身。这种FactoryBean的机制可以为我们提供一个很好地封装机制,如封装Proxy、RMI、JNDI等。

getObject方法就是主要的FactoryBean的接口,需要实现特定的工厂的生产过程。

BeanPostProcessor的实现

BeanPostProcessor是一个监听器,可以监听容器触发的事件。将它向IoC容器注册后,容器中管理的Bean具备了接收IoC容器事件回调的能力。

BeanPostProcessor的使用非常简单,设计一个具体的后置处理器来实现,同时这个具体的后置处理器需要实现接口类BeanPostProcessor,然后设置到XML的Bean配置文件中。

BeanPostProcessor是一个接口类:

public interface BeanPostProcessor {

	/**
	 * 在Bean的初始化前提供回调入口
	 */
	@Nullable
	default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
		return bean;
	}

	/**
	 * 在Bean初始化后提供回调入口
	 */
	@Nullable
	default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
		return bean;
	}

}

这两个回调的处罚都是和容器管理Bean的生命周期相关的,参数都是Bean的实例化对象和Bean的名字。

在这里插入图片描述
postProcessorBeforeInitialization是在populateBean完成之后被调用的,从BeanPostProcessor中的一个回调接口入手,对另一个回调接口PostProcessorAfterInitialization方法的调用。在populateBean方法中的initializeBean调用。

Object exposedObject = bean;
		try {
			populateBean(beanName, mbd, instanceWrapper);
			// 在完成对Bean的生成和依赖注入后,开始对Bean初始化
			// 这份初始化过程包含了对后置处理器的回调
			exposedObject = initializeBean(beanName, exposedObject, mbd);
		}
protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
		if (System.getSecurityManager() != null) {
			AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
				invokeAwareMethods(beanName, bean);
				return null;
			}, getAccessControlContext());
		}
		else {
			invokeAwareMethods(beanName, bean);
		}
		// 这里是对后置处理器BeanPostProcessors的PostProcessBeforeInitialization的回调方法的调用
		Object wrappedBean = bean;
		if (mbd == null || !mbd.isSynthetic()) {
			wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
		}

		// 调用Bean的初始化方法,这个初始化方法是在BeanDefinition中通过定义init-method
		// 属性指定的,同时,如果Bean实现了InitiallizingBean接口,那么这个Bean的afterPropertiesSet实现也会被调用
		try {
			invokeInitMethods(beanName, wrappedBean, mbd);
		}
		catch (Throwable ex) {
			throw new BeanCreationException(
					(mbd != null ? mbd.getResourceDescription() : null),
					beanName, "Invocation of init method failed", ex);
		}
		// 这里是对后置处理器BeanPostProcessor的PostProcessAfterInitialization的回调方法调用
		if (mbd == null || !mbd.isSynthetic()) {
			wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
		}

		return wrappedBean;
	}

从以上代码实现中可以看到这两个Bean后置处理器定义的接口方法,一前一后,围绕着Bean定义的init-method方法调用,与IoC容器对Bean的管理有机结合起来了。

autowiring (自动依赖装配)的实现

在之前对IoC容器实现原理的分析中,一直是通过BeanDefinition的属性值和构造函数以显示的方式对Bean的依赖关系进行管理的。在spring中,相对这种显式的依赖管理方式,IoC容器还提供了自动依赖装配的方式,在这个过程中,不需要对Bean属性做显式的依赖关系声明,只需要配置好autowiring属性。IoC容器会根据这个属性的配置,使用反射自动查找属性的类型或名字,然后基于属性的类型或名字来自动匹配IoC容器中的Bean,从而自动完成依赖注入。

autowiring属性在对Bean属性进行依赖注入时起作用,对Bean属性依赖注入的实现原理,而从完成对Bean属性的自动依赖装配,是在populateBean中实现的。

populateBean的实现中,在处理一般的Bean之前,先对autowiring属性进行处理。如果当前的Bean配置了autowire_by_name和autowire_by_type属性。

首先通过反射机制从当前Bean中得到需要注入的属性名,然后使用这个属性名向容器申请与之同名的Bean,实际又触发了另一个Bean的生成和依赖注入的过程。

int resolvedAutowireMode = mbd.getResolvedAutowireMode();
		// 开始依赖注入的过程,先处理autowire注入
		if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
			MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
			// 根据Bean的名字或类型完成Bean的autowire
			if (resolvedAutowireMode == AUTOWIRE_BY_NAME) {
				autowireByName(beanName, mbd, bw, newPvs);
			}
			if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
				autowireByType(beanName, mbd, bw, newPvs);
			}
			pvs = newPvs;
		}

通过调用autowireByName和autowireByType来完成自动依赖装配;

对autowireByName来说,首先需要得到当前Bean的属性名,这些属性名已经在BeanWrapper和BeanDefinition中封装好了,然后是对这一系列属性名进行匹配的过程。在匹配的过程中,因为已经有了属性的名字,所以可以直接使用属性名作为Bean名字向容器索取Bean,这个getBean会触发当前Bean的依赖Bean的依赖注入,从而得到属性对应的依赖Bean。在执行完这个getBean后,把这个依赖Bean注入到当前Bean的属性中取去,这样就完成了通过这个以来属性名完成依赖注入的过程。

protected void autowireByName(
			String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {

		String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
		for (String propertyName : propertyNames) {
			if (containsBean(propertyName)) {
				// 使用取得的当前Bean的属性名作为Bean的名字,向IoC容器索取Bean,
				// 然后把从容器得到的Bean设置到当前Bean的属性中去
				Object bean = getBean(propertyName);
				pvs.add(propertyName, bean);
				registerDependentBean(propertyName, beanName);
				if (logger.isTraceEnabled()) {
					logger.trace("Added autowiring by name from bean name '" + beanName +
							"' via property '" + propertyName + "' to bean named '" + propertyName + "'");
				}
			}
			else {
				if (logger.isTraceEnabled()) {
					logger.trace("Not autowiring property '" + propertyName + "' of bean '" + beanName +
							"' by name: no matching bean found");
				}
			}
		}
	}

Bean的依赖检查

在一般情况下,Bean的依赖注入是在应用第一次向容器索要Bean的时候发生的,在这个时候,不能保证注入一定能成功,如果需要重新检查这些依赖关系的有效性,会是一件很繁琐的事情。

为了解决这样的问题,在spring IoC容器中,设计了一个依赖检查特性,通过它,spring可以帮助应用检查是否所有的属性都被正确设置。

在具体使用的时候,应用只需要在Bean定义中设置dependency-check属性来指定一来检查模式即可。模式包括:none、simple、object、all四种模式,默认为none。

具体的实现代码是在AbstractAutowireCapableBeanFactory实现createBean的过程中完成的。这个过程会对Bean的Dependencies属性进行检查,如果发现不满足要求,就会抛出异常通知应用。

protected void checkDependencies(
			String beanName, AbstractBeanDefinition mbd, PropertyDescriptor[] pds, @Nullable PropertyValues pvs)
			throws UnsatisfiedDependencyException {

		int dependencyCheck = mbd.getDependencyCheck();
		for (PropertyDescriptor pd : pds) {
			if (pd.getWriteMethod() != null && (pvs == null || !pvs.contains(pd.getName()))) {
				boolean isSimple = BeanUtils.isSimpleProperty(pd.getPropertyType());
				boolean unsatisfied = (dependencyCheck == AbstractBeanDefinition.DEPENDENCY_CHECK_ALL) ||
						(isSimple && dependencyCheck == AbstractBeanDefinition.DEPENDENCY_CHECK_SIMPLE) ||
						(!isSimple && dependencyCheck == AbstractBeanDefinition.DEPENDENCY_CHECK_OBJECTS);
				if (unsatisfied) {
					throw new UnsatisfiedDependencyException(mbd.getResourceDescription(), beanName, pd.getName(),
							"Set this property value or disable dependency checking for this bean.");
				}
			}
		}
	}

Bean对IoC容器的感知

容器管理的Bean一般不需要了解容器的状态和直接使用容器,但在某些情况下,需要在Bean中直接对IoC容器进行操作的,这时候,就需要在Bean中设定对容器的感知,springIoC容器也提供了该功能,它是通过特定的aware接口来完成的,aware接口有这些:

  • BeanNameAware:可以在Bean中得到它在IoC容器的Bean实例名称。
  • BeanFactoryAware:可以在Bean中得到Bean所在的IoC容器,从而直接在Bean中使用IoC容器服务。
  • ApplicationContextAware:可以在Bean中得到Bean所在的应用上下文,从而直接在Bean中使用应用上下文服务。
  • MessageSourceAware:在Bean中可以得到消息源。
  • ApplicationEventPublisherAware:在Bean中可以得到应用上下文的事件发布器,从而可以在Bean中发布应用上下文事件。
  • ResourceLoaderAware:在Bean中可以得到ResourceLoader,从而在Bean中使用ResourceLoader加载外部对应的Resource资源。
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值