Spring读源码系列05----bean的加载---下

Posted 大忽悠爱忽悠

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring读源码系列05----bean的加载---下相关的知识,希望对你有一定的参考价值。

Spring读源码系列05----bean的加载---下


阅读本系列之前,建议先从本专栏的两个不同视角学习spring的系列作为入门学习点(这两个系列会持续更新),先大体理解spring的架构设计与精髓,然后再来阅读本系列,深入源码分析,而不再纸上谈兵。

从整体来学spring系列文章:

Spring复杂的BeanFactory继承体系该如何理解? ----上

Spring复杂的BeanFactory继承体系该如何理解? ----中

Spring复杂的BeanFactory继承体系该如何理解?—中下

Spring复杂的BeanFactory继承体系该如何理解?—下

Spring复杂的IOC容器之短小的注解篇

Spring繁华的AOP王国—第一讲

Spring繁华的AOP王国—第二讲

Spring繁华的AOP王国—第三讲

Spring繁华的AOP王国----第四讲

Spring繁华的AOP王国—第五讲之应用案例和扩展

该系列持续更新中…


独特视角学习spring系列文章:

不一样的视角来学习Spring源码之容器与Bean—上

不一样的视角来学习Spring源码之容器与Bean—下

不一样的视角来学习Spring源码之AOP—上

不一样的视角来学习Spring源码之AOP—中

不一样的视角来学习Spring源码之AOP—下

该系列持续更新中…


本系列文章:

Spring读源码系列01—Spring核心类及关联性介绍

Spring读源码系列02----默认标签解析过程

Spring读源码系列03----自定义标签解析(待续中)

Spring读源码系列04----bean的加载—上

Spring读源码系列05----bean的加载—中


番外篇:

Spring读源码系列番外篇—01–PropertyValue相关类


初始化Bean


先回顾一下初始化方法的调用时机:

	protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
			throws BeanCreationException 

		// Instantiate the bean.
		BeanWrapper instanceWrapper = null;
		if (mbd.isSingleton()) 
			instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
		
		if (instanceWrapper == null) 
			instanceWrapper = createBeanInstance(beanName, mbd, args);
		
		Object bean = instanceWrapper.getWrappedInstance();
		Class<?> beanType = instanceWrapper.getWrappedClass();
		if (beanType != NullBean.class) 
			mbd.resolvedTargetType = beanType;
		

		// Allow post-processors to modify the merged bean definition.
		synchronized (mbd.postProcessingLock) 
			if (!mbd.postProcessed) 
				try 
					applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
				
				catch (Throwable ex) 
					throw new BeanCreationException(mbd.getResourceDescription(), beanName,
							"Post-processing of merged bean definition failed", ex);
				
				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.isTraceEnabled()) 
				logger.trace("Eagerly caching bean '" + beanName +
						"' to allow for resolving potential circular references");
			
			addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
		

		// Initialize the bean instance.
		Object exposedObject = bean;
		try 
			populateBean(beanName, mbd, instanceWrapper);
			//这个就是我们要讲的方法!!!
			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(), beanName, "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 " +
								"'getBeanNamesForType' 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(), beanName, "Invalid destruction signature", ex);
		

		return exposedObject;
	

AbstractAutowireCapableBeanFactory#initializeBean—初始化Bean

	protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) 
	//1.触发aware相关接口的注入
		if (System.getSecurityManager() != null) 
			AccessController.doPrivileged((PrivilegedAction<Object>) () -> 
				invokeAwareMethods(beanName, bean);
				return null;
			, getAccessControlContext());
		
		else 
			invokeAwareMethods(beanName, bean);
		

//2.后置处理器的应用
		Object wrappedBean = bean;
		if (mbd == null || !mbd.isSynthetic()) 
			wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
		

//3.调用init-method反复
		try 
			invokeInitMethods(beanName, wrappedBean, mbd);
		
		catch (Throwable ex) 
			throw new BeanCreationException(
					(mbd != null ? mbd.getResourceDescription() : null),
					beanName, "Invocation of init method failed", ex);
		
		//4.后置处理器的应用
		if (mbd == null || !mbd.isSynthetic()) 
			wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
		

		return wrappedBean;
	

AbstractAutowireCapableBeanFactory#invokeAwareMethods—激活aware方法

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

说实话,这段源码实在没啥好讲的,aware接口本身就比较常用,大家应该也能猜到是这种方式实现的,如果你有自定义的需求,那么可以通过增加一个适当的后置处理器来进行实现


AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsBeforeInitialization

	@Override
	public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
			throws BeansException 

		Object result = existingBean;
		for (BeanPostProcessor processor : getBeanPostProcessors()) 
			Object current = processor.postProcessBeforeInitialization(result, beanName);
			if (current == null) 
				return result;
			
			result = current;
		
		return result;
	

AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsAfterInitialization

	@Override
	public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
			throws BeansException 

		Object result = existingBean;
		for (BeanPostProcessor processor : getBeanPostProcessors()) 
			Object current = processor.postProcessAfterInitialization(result, beanName);
			if (current == null) 
				return result;
			
			result = current;
		
		return result;
	

激活自定义的init方法

/**
	 * Give a bean a chance to react now all its properties are set,
	 * and a chance to know about its owning bean factory (this object).
	 * This means checking whether the bean implements InitializingBean or defines
	 * a custom init method, and invoking the necessary callback(s) if it does.
	 */
	protected void invokeInitMethods(String beanName, Object bean, @Nullable RootBeanDefinition mbd)
			throws Throwable 
        //如果是isInitializingBean ,会调用其重新的afterPropertiesSet方法
		boolean isInitializingBean = (bean instanceof InitializingBean);
		if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) 
			if (logger.isTraceEnabled()) 
				logger.trace("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
			
			if (System.getSecurityManager() != null) 
				try 
					AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> 
						((InitializingBean) bean).afterPropertiesSet();
						return null;
					, getAccessControlContext());
				
				catch (PrivilegedActionException pae) 
					throw pae.getException();
				
			
			else 
				((InitializingBean) bean).afterPropertiesSet();
			
		
      
		if (mbd != null && bean.getClass() != NullBean.class) 
		//调用自定义初始化方法
			String initMethodName = mbd.getInitMethodName();
			if (StringUtils.hasLength(initMethodName) &&
					!(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
					!mbd.isExternallyManagedInitMethod(initMethodName)) 
				invokeCustomInitMethod(beanName, bean, mbd);
			
		
	

注册DisposableBean


先回顾一下销毁方法处理逻辑在哪里被调用的:

	protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
			throws BeanCreationException 

		// Instantiate the bean.
		BeanWrapper instanceWrapper = null;
		if (mbd.isSingleton()) 
			instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
		
		if (instanceWrapper == null) 
			instanceWrapper = createBeanInstance(beanName, mbd, args);
		
		Object bean = instanceWrapper.getWrappedInstance();
		Class<?> beanType = instanceWrapper.getWrappedClass();
		if (beanType != NullBean.class) 
			mbd.resolvedTargetType = beanType;
		

		// Allow post-processors to modify the merged bean definition.
		synchronized (mbd.postProcessingLock) 
			if (!mbd.postProcessed) 
				try 
					applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
				
				catch (Throwable ex) 
					throw new BeanCreationException(mbd.getResourceDescription(), beanName,
							"Post-processing of merged bean definition failed", ex);
				
				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.isTraceEnabled()) 
				logger.trace("Eagerly caching bean '" + beanName +
						"' to allow for resolving potential circular references");
			
			addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
		

		// Initialize the bean instance.
		Object exposedObject = bean;
		try 
			populateBean(beanName, mbd, instanceWrapper);
			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(), beanName, "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 =

以上是关于Spring读源码系列05----bean的加载---下的主要内容,如果未能解决你的问题,请参考以下文章

Spring源码系列 —— 构造和初始化上下文

Spring读源码系列02----默认标签解析过程

Spring读源码系列01---Spring核心类及关联性介绍

Spring读源码系列07----容器扩展功能--中

Spring读源码系列06----容器扩展功能--上

Spring读源码系列08----容器扩展功能--下