Spring 源码学习系列BeanNameAware#setBeanName 方法的调用时机

Posted 明明如月学长

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring 源码学习系列BeanNameAware#setBeanName 方法的调用时机相关的知识,希望对你有一定的参考价值。

一、背景

前一节我们研究了 《ApplicationContextAware 方法的调用时机》 ,对 IOC 容器最核心的方法 refresh 有了初步的了解。

这节,我们将借助 BeanNameAware 方法的调用时机对 Bean 的初始化进一步学习。

二、分析

2.1 代码示例

实现 BeanNameAware接口:

package org.example.aware.bean;

import org.springframework.beans.factory.BeanNameAware;
import org.springframework.stereotype.Component;

@Component
public class NameAwaredTestBean implements BeanNameAware 
    @Override
    public void setBeanName(String name) 
        System.out.println("beanName:" + name);
    

编写配置:

package org.example.aware.config;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@Configuration
@ComponentScan("org.example.aware.bean")
public class AwareConfiguration 



执行:

package org.example.aware;

import org.example.aware.bean.NameAwaredTestBean;
import org.example.aware.config.AwareConfiguration;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class AwareApplication 

    public static void main(String[] args) throws Exception 
        ApplicationContext ctx = new AnnotationConfigApplicationContext(AwareConfiguration.class);
        NameAwaredTestBean atBean = ctx.getBean(NameAwaredTestBean.class);
        System.out.println(atBean);
    


2.2 由外到内

先猜想后验证法


按照“国际惯例” 我们先进行猜测BeanNameAware 应该比前文的 ApplicationContextAware 的时机更早,因为在 setBeanName 里我们可以修改 bean 的名称,而 ApplicationContextAware#setApplicationContext 里面很可能会用到 bean 的名称来构造策略 Map。


接下来我们进行验证。按照“老传统” 在 setBeanName 方法上断点。
发现调用来自:

private void invokeAwareMethods(String beanName, Object bean) 
		if (bean instanceof Aware) 
			//1 设置 BeanName
			if (bean instanceof BeanNameAware) 
			// 调用来自这里
				((BeanNameAware) bean).setBeanName(beanName);
			
			
       		 //2 设置 BeanClassLoader
			if (bean instanceof BeanClassLoaderAware) 
				ClassLoader bcl = getBeanClassLoader();
				if (bcl != null) 
					((BeanClassLoaderAware) bean).setBeanClassLoader(bcl);
				
			
			
			//3 设置 BeanFactory
			if (bean instanceof BeanFactoryAware) 
			
				((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
			
		
	

从这里我们可以看出 BeanClassLoaderAware#setBeanClassLoaderBeanFactoryAware#setBeanFactory 都在 invokeAwareMethods 方法里一起调用。

再上追溯一层:
AbstractAutowireCapableBeanFactory#initializeBean

/**
	 * Initialize the given bean instance, applying factory callbacks
	 * as well as init methods and bean post processors.
	 * 初始化给定的  Bean 实例,应用 init 方法和 bean 后置处理器
	 * <p>Called from @link #createBean for traditionally defined beans,
	 * and from @link #initializeBean for existing bean instances.
	 * 调用来自 createBean 
	 * @param beanName the bean name in the factory (for debugging purposes)
	 * @param bean the new bean instance we may need to initialize
	 * @param mbd the bean definition that the bean was created with
	 * (can also be @code null, if given an existing bean instance)
	 * @return the initialized bean instance (potentially wrapped)
	 * @see BeanNameAware
	 * @see BeanClassLoaderAware
	 * @see BeanFactoryAware
	 * @see #applyBeanPostProcessorsBeforeInitialization
	 * @see #invokeInitMethods
	 * @see #applyBeanPostProcessorsAfterInitialization
	 */
	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()) 
		// 执行 BeanPostProcessorsBeforeInitialization
			wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
		

		try 
		// 执行 Init 方法
			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()) 
		// 执行  BeanPostProcessorsAfterInitialization
			wrappedBean = 			applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
		

		return wrappedBean;
	

主要流程:

其中 invokeInitMethods 方法的源码如下:

	/**
	 * 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.
	 * 检查当前 bean 是否实现了  InitializingBean 接口或者定义了  init 方法,如果有则执行调用
	 * @param beanName the bean name in the factory (for debugging purposes)
	 * @param bean the new bean instance we may need to initialize
	 * @param mbd the merged bean definition that the bean was created with
	 * (can also be @code null, if given an existing bean instance)
	 * @throws Throwable if thrown by init methods or by the invocation process
	 * @see #invokeCustomInitMethod
	 */
	protected void invokeInitMethods(String beanName, Object bean, @Nullable RootBeanDefinition mbd)
			throws Throwable 

// 检查是否实现了 InitializingBean 接口
		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#afterPropertiesSet 方法
				((InitializingBean) bean).afterPropertiesSet();
			
		

		if (mbd != null && bean.getClass() != NullBean.class) 
		// 获取  init 方法名 并执行调用
			String initMethodName = mbd.getInitMethodName();
			if (StringUtils.hasLength(initMethodName) &&
					!(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
					!mbd.isExternallyManagedInitMethod(initMethodName)) 
				invokeCustomInitMethod(beanName, bean, mbd);
			
		
	

可以看到这里先执行 InitializingBean#afterPropertiesSet 然后再执行自定义 init 方法。

再往上追溯和前一篇文章非常类似。
AbstractAutowireCapableBeanFactory#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(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
			throws BeanCreationException 

		// Instantiate the bean.
		// 实例化 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, () ->
			// 构造 早期暴漏的 bean 引用,来解决循环依赖问题 
			
			getEarlyBeanReference(beanName, mbd, bean));
		

		// 初始化 bean 实例.
		Object exposedObject = bean;
		try 
		
			populateBean(beanName, mbd, instanceWrapper);
			// 【重要】 执行到这里( bean 初始化)
			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);
			
		

	// 省略部分代码

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

		return exposedObject;
	

再往上层回溯到 DefaultSingletonBeanRegistry#getSingleton 这里:

/**
	 * Return the (raw) singleton object registered under the given name,
	 * creating and registering a new one if none registered yet.
	 * @param beanName the name of the bean
	 * @param singletonFactory the ObjectFactory to lazily create the singleton
	 * with, if necessary
	 * @return the registered singleton object
	 */
	public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) 
		Assert.notNull(beanName, "Bean name must not be null");
		synchronized (this.singletonObjects) 
		// 先通过 bean 名称从单例 bean 缓存中获取 bean 实例
			Object singletonObject = this.singletonObjects.get(beanName);
			// 如果没有执行创建
			if (singletonObject == null) 
				if (this.singletonsCurrentlyInDestruction) 
					throw new BeanCreationNotAllowedException(beanName,
							"Singleton bean creation not allowed while singletons of this factory are in destruction " +
							"(Do not request a bean from a BeanFactory in a destroy method implementation!)");
				
				if (logger.isDebugEnabled()) 
					logger.debug("Creating shared instance of singleton bean '" + beanName + "'");
				
				// 执行单例bean 创建的前置逻辑
				beforeSingletonCreation(beanName);
				boolean newSingleton = false;
				boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
				if (recordSuppressedExceptions) 
					this.suppressedExceptions = new LinkedHashSet<>();
				
				try 
				//【重要】执行到这里
				// 创建单例 bean
					singletonObject = singletonFactory.getObject();
					newSingleton = true;
				
				catch (IllegalStateException ex) 
					// Has the singleton object implicitly appeared in the meantime ->
					// if yes, proceed with it since the exception indicates that state.
					singletonObject = this.singletonObjects.get(beanName);
					if (singletonObject == null) 
						throw ex;
					
				
				catch (BeanCreationException ex) 
					if (recordSuppressedExceptions) 
						for (Exception suppressedException : this.suppressedExceptions) 
							ex.addRelatedCause(suppressedException);
						
					
					throw ex;
				
				finally 
					if (recordSuppressedExceptions) 
						this.suppressedExceptions = null;
					
					// 执行单例bean 创建的后置逻辑
					afterSingletonCreation(beanName);
				
// 如果是新创建的单例 Bean ,则添加到 beanName 到 单例 bean 的缓存中
				if (newSingleton) 
					addSingleton(beanName, singletonObject);
				
			
			return singletonObject;
		
	

再往上一层:

/**
	 * Return an instance, which may be shared or independent, of the specified bean.
	 */
	@SuppressWarnings("unchecked")
	protected <T> T doGetBean(
			String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
			throws BeansException 

// 省略部分代码
//1 如果是单例,创建单例 bean
				// Create bean instance.
				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);
				
// 2 prototype

				else if (mbd.isPrototype()) 
					// It's a prototype -> create a new instance.
				  // 由于是  prototype -> 每次都新建一个实例
					Object prototypeInstance = null;
					try 
						beforePrototypeCreation(beanName);
						prototypeInstance = createBean(beanName, mbd, args);
					
					finally 
						afterPrototypeCreation(beanName);
					
					bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
				

// 省略部分代码

		return (T) bean;
	

再往上追溯:

	/**
	 * Finish the initialization of this context's bean factory,
	 * initializing all remaining singleton beans.
	 */
	protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) 
		// Initialize conversion service for this context.
		if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&
				beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) 
			beanFactory.setConversionService(
					beanFactory.Spring读源码系列之AOP--03---aop底层基础类学习

Spring 源码学习系列BeanNameAware#setBeanName 方法的调用时机

Spring读源码系列之AOP--05---aop常用工具类学习

Spring源码深度解析学习系列注册解析的BeanDefinition

Spring 源码学习系列ApplicationContextAware#setApplicationContext 方法的调用时机

Spring 源码学习系列ApplicationContextAware#setApplicationContext 方法的调用时机