Bean的生命周期流程-上

Posted 热爱编程的大忽悠

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Bean的生命周期流程-上相关的知识,希望对你有一定的参考价值。

Bean的生命周期流程-上


引言

Spring拥有一套完善的Bean生命周期体系,而使得这套生命周期体系具有高扩展性的关键在于Bean生命周期回调接口,通过这些接口我们可以动态的插入Bean生命周期初始化的各个阶段,然后进行一系列动态代理,自动注入,属性校验的工作。

今天,我们来一起看看Bean的生命周期流程,即getBean流程是怎样实现的。


getBean

AbstractBeanFactory的getBean方法会调用doGetBean方法:

AbstractBeanFactory的doGetBean方法我们只关注单例Bean的创建流程:

protected <T> T doGetBean(
			String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
			throws BeansException 
         //获取真正的beanName
         //1、如果是FactoryBean,会去掉Bean开头的&符号
		 // 2、如存在多层别名映射A->B->C->D,传入D,最终会返回A
		String beanName = transformedBeanName(name);
		Object beanInstance;

		//1.尝试从缓存中获取已经实例化好的单例bean
		//2.存在循环依赖,从signleFactory中获取提早暴露的bean
		Object sharedInstance = getSingleton(beanName);
		//缓存中获取到了对应的bean
		if (sharedInstance != null && args == null) 
			if (logger.isTraceEnabled()) 
			    //如果singletonsCurrentlyInCreation集合中包含了该beanName
			    //说明此时获取到的是提早暴露出来的bean--此时存在循环依赖
				if (isSingletonCurrentlyInCreation(beanName)) 
					logger.trace("Returning eagerly cached instance of singleton bean '" + beanName +
							"' that is not fully initialized yet - a consequence of a circular reference");
				
				else 
				    //说明获取到的是已经实例化好的bean
					logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
				
			
			//对factoryBean进行特殊处理--下面会进行解释
			beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, null);
		

		else 
			//原型对象不允许循环创建,如果是原型对象正在创建,那就抛异常
			if (isPrototypeCurrentlyInCreation(beanName)) 
				throw new BeanCurrentlyInCreationException(beanName);
			

			//如果存在父容器,并且只在子容器中不包含当前bean定义的情况下,才会尝试从父容器中getBean
			// 这就是为何,我们扫描controller,哪怕不加排除什么的,也不会出问题的原因~
            //因为Spring中的单例Bean只会被实例化一次(即使父子容器都扫描了)
			BeanFactory parentBeanFactory = getParentBeanFactory();
			if (parentBeanFactory != null && !containsBeanDefinition(beanName)) 
			   //和transformedBeanName处理类似,多加了一个获取FactoryBean本身的判断条件
			    String nameToLookup = originalBeanName(name);
				if (parentBeanFactory instanceof AbstractBeanFactory) 
					return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
							nameToLookup, requiredType, args, typeCheckOnly);
				
				else if (args != null) 
					return (T) parentBeanFactory.getBean(nameToLookup, args);
				
				else if (requiredType != null) 
					return parentBeanFactory.getBean(nameToLookup, requiredType);
				
				else 
					return (T) parentBeanFactory.getBean(nameToLookup);
				
			
            
            //在alreadyCreated记录一下当前beanName,表示当前bean已经创建或者将要创建
			if (!typeCheckOnly) 
				markBeanAsCreated(beanName);
			
            
			...
			try 
				...
				//将一开始通过包扫描或者注解扫描等方式得到的不同类型的BeanDefinition都转换为RootBeanDefinition 
				RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
				//当前beanDefinition不能是抽象的
				checkMergedBeanDefinition(mbd, beanName, args);

				//如果bean上标注了@DependsOn注解,那么解析的时候会将注解信息都存放到当前BeanDefinition的dependsOn属性中去
				String[] dependsOn = mbd.getDependsOn();
				//将依赖的bean先进行初始化
				if (dependsOn != null) 
					for (String dep : dependsOn) 
					    //判断是否存在A dependsOn B,然后B又dependsOn A的情况,或者是涉及到更多bean之间的循环依赖
						if (isDependent(beanName, dep)) 
							throw new BeanCreationException(mbd.getResourceDescription(), beanName,
									"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
						
						//不存在因为@DependsOn注解产生的循环依赖,就正常将依赖的bean进行初始化
						registerDependentBean(dep, beanName);
						try 
							getBean(dep);
						
						catch (NoSuchBeanDefinitionException ex) 
							throw new BeanCreationException(mbd.getResourceDescription(), beanName,
									"'" + beanName + "' depends on missing bean '" + dep + "'", ex);
						
					
				

				//单例bean的创建过程
				if (mbd.isSingleton()) 
					sharedInstance = getSingleton(beanName, () -> 
						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;
						
					);
					//处理factoryBean的转换情况
					beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
				
		    //其他scope类型bean的处理		
		    ....				
			catch (BeansException ex) 
				beanCreation.tag("exception", ex.getClass().toString());
				beanCreation.tag("message", String.valueOf(ex.getMessage()));
				cleanupAfterBeanCreationFailure(beanName);
				throw ex;
			
			finally 
				beanCreation.end();
			
		
         //通过TypeConverter将bean转换为指定的类型
		return adaptBeanInstance(name, beanInstance, requiredType);
	

getSingleton

DefaultSingletonBeanRegistr的getSingleton方法:

public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) 
		Assert.notNull(beanName, "Bean name must not be null");
		synchronized (this.singletonObjects) 
		    //先尝试从单例缓冲池中获取已经实例化好的bean
			Object singletonObject = this.singletonObjects.get(beanName);
			if (singletonObject == null) 
			    //一般缓存中此时是还没有创建好当前bean的
			    //如果调用了destroySingletons方法销毁所有单例bean,那么此时bean就不允许再被创建了
				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 + "'");
				
		        // 创建前置检查:
		        //1、若在inCreationCheckExclusions里面,表示不需要进行创建中检查
				//2、如果需要进行创建中检查,就把当前bean加入singletonsCurrentlyInCreation去,表示这个Bean正在创建中
				beforeSingletonCreation(beanName);
				boolean newSingleton = false;
				...
				try 
				    //getObject方法最终调用的是createBean方法
					singletonObject = singletonFactory.getObject();
					newSingleton = true;
				
				//异常捕获
				...
				finally 
					if (recordSuppressedExceptions) 
						this.suppressedExceptions = null;
					
					// 创建完成后再检查一遍。做的操作为:从正在创建缓存中移除
					afterSingletonCreation(beanName);
				
				if (newSingleton) 
				    //将关于当前bean提前暴露出来的bean都清理掉,然后将当前bean加入单例缓冲池中  			
					addSingleton(beanName, singletonObject);
				
			
			return singletonObject;
		
	

createBean

开始创建Bean AbstractAutowireCapableBeanFactory#createBean 提供此方法的抽象类为:AbstractBeanFactory,由子类去实现创建的逻辑。

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

		if (logger.isTraceEnabled()) 
			logger.trace("Creating instance of bean '" + beanName + "'");
		
		RootBeanDefinition mbdToUse = mbd;

		// 通过classLoader加载beanDefinition中保存的className得到对应的class
		//这一步用于确定对应的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 
			// 这里主要是解析<lookup-method name="getFruit" bean="bananer"/>类似这种方式的依赖注入(Spring支持lookup-method,replace-method两个依赖注入的方式)
			// 它相当于调用指定类里面的指定方法进行注入,所以需要考虑到方法重载的情况,因此这个方法解析的就是这种情况
			// 由于项目中一般这么使用,也非常的不大众,具体原理此处省略
			mbdToUse.prepareMethodOverrides();
		
		catch (BeanDefinitionValidationException ex) 
			throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
					beanName, "Validation of method overrides failed", ex);
		

		try 
		     // 从doc解释:给BeanPostProcessors一个机会来返回一个代理对象代替目标对象
			// 1、具体逻辑是判断当前Spring容器是否注册了实现了InstantiationAwareBeanPostProcessor接口的后置处理器如果有,则依次调用其中的applyBeanPostProcessorsBeforeInstantiation方法,如果中间任意一个方法返回不为null,直接结束调用。
			// 2、applyBeanPostProcessorsBeforeInstantiation返回不为null的情况下,然后依次所有注册的BeanPostProcessor的postProcessAfterInitialization方法。
			//默认情况下,默认注册的bean后置处理器,在该处都不会做任何事情
			Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
			if (bean != null) 
				return bean;
			
		
		catch (Throwable ex) 
			throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
					"BeanPostProcessor before instantiation of bean failed", ex);
		

		try 
		    //真正尝试创建bean
			Object beanInstance = doCreateBean(beanName, mbdToUse, args);
			if (logger.isTraceEnabled()) 
				logger.trace("Finished creating instance of bean '" + beanName + "'");
			
			return beanInstance;
		
		...
	

后置处理器类型区分

BeanPostProcessor和InstantiationAwareBeanPostProcessor这两个接口,是比较容易搞混的,需要这里注意区分一下。

InstantiationAwareBeanPostProcessor代表了Spring的另外一段生命周期:实例化。先区别一下Spring Bean的实例化和初始化两个阶段的主要作用:

  • 实例化:实例化的过程是一个创建Bean的过程,即调用Bean的构造函数,单例的Bean放入单例池中
  • 初始化:初始化的过程是一个赋值的过程,即调用Bean的setter,设置Bean的属性

所以现在就清楚了:InstantiationAwareBeanPostProcessor是作用于 实例化 前后,所以是先执行的。

BeanPostProcessor是作用于 初始化 前后,给Bean各个属性赋值的时候执行的(比如我们的属性依赖注入,都是这个时候生效的)

// Instantiation:[ɪnstænʃɪ'eɪʃən] 实例化,例示
// Initialization:[ɪˌnɪʃəlaɪ'zeɪʃn] 初始化,设定初始值

public interface BeanPostProcessor 
	@Nullable
	default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException 
		return bean;
	
	@Nullable
	default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException 
		return bean;
	

子接口:InstantiationAwareBeanPostProcessor
public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor 
	@Nullable
	default Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException 
		return null;
	
	default boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException 
		return true;
	
	@Nullable
	default PropertyValues postProcessPropertyValues(
			PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException 

		return pvs;
	
    @Nullable
	default PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName)
			throws BeansException 

		return null;
	

ApplicationListenerDetector重点实现了postProcessAfterInitialization方法:将那些实现ApplicationListener接口的bean,在它们初始化之后,将它们注册到applicationContext的事件多播器上。并在这些ApplicationListener bean销毁之前,将它们从applicationContext的事件多播器上移除。

子接口SmartInstantiationAwareBeanPostProcessor 继承自 InstantiationAwareBeanPostProcessor;
但是SmartInstantiationAwareBeanPostProcessor多了三个方法:

// 从名字上,它有个Smart,是比较智能一些的
public interface SmartInstantiationAwareBeanPostProcessor extends InstantiationAwareBeanPostProcessor 
	// 预测Bean的类型,返回第一个预测成功的Class类型,如果不能预测返回null
	default Class<?> predictBeanType(Class<?> beanClass, String beanName) throws BeansException 
		return null;
	
	
	// 选择合适的构造器,比如目标对象有多个构造器,在这里可以进行一些定制化,选择合适的构造器
	// beanClass参数表示目标实例的类型,beanName是目标实例在Spring容器中的name
	// 返回值是个构造器数组,如果返回null,会执行下一个PostProcessor的determineCandidateConstructors方法;否则选取该PostProcessor选择的构造器
	default Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, String beanName)
			throws BeansException 

		return null;
	
	
	// 获得提前暴露的bean引用。主要用于解决循环引用的问题
	// 只有单例对象才会调用此方法
	default Object getEarlyBeanReference(Object bean, String beanName) throws BeansException 
		return bean;
	

在对bean进行依赖注入时,定位bean实例化使用的构造器,就是通过搜寻容器中所有SmartInstantiationAwareBeanPostProcessor类型后置处理器实现,然后依次调用其determineCandidateConstructors方法对bean进行解析获取的。


默认只有自动代理创建重写了getEarlyBeanReference方法,尝试将提早暴露出来的bean也进行代理。


MergedBeanDefinitionPostProcessor:

public interface MergedBeanDefinitionPostProcessor extends BeanPostProcessor 
	void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName);
	
	default void resetBeanDefinition(String beanName) 
	

用来将RootBeanDefinition暴露出来的回调。看看它的一些主要实现:

//InitDestroyAnnotationBeanPostProcessor
	@Override
	public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) 
		LifecycleMetadata metadata = findLifecycleMetadata(beanType);
		metadata.checkConfigMembers(beanDefinition);
	

//CommonAnnotationBeanPostProcessor
	@Override
	public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) 
		super.postProcessMergedBeanDefinition(beanDefinition, beanType, beanName);
		InjectionMetadata metadata = findResourceMetadata(beanName, beanType, null);
		metadata.checkConfigMembers(beanDefinition);
	

//AutowiredAnnotationBeanPostProcessor
	@Override
	public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) 
		InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null);
		metadata.checkConfigMembers(beanDefinition);
	

//ApplicationListenerDetector
	@Override
	public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) 
		this.singletonNames.put(beanName, beanDefinition.isSingleton());
	

稍微总结下:

  • InstantiationAwareBeanPostProcessor接口的主要作用在于目标对象的实例化过程中需要处理的事情,包括实例化对象的前后过程以及实例的属性设置
  • postProcessBeforeInstantiation方法是最先执行的方法,它在目标对象实例化之前调用,该方法的返回值类型是Object,我们可以返回任何类型的值。由于这个时候目标对象还未实例化,所以这个返回值可以用来代替原本该生成的目标对象的实例(比如代理对象)。如果该方法的返回值代替原本该生成的目标对象,后续只有postProcessAfterInitialization方法会调用,其它方法不再调用;否则按照正常的流程走
  • postProcessAfterInstantiation方法在目标对象实例化之后调用,这个时候对象已经被实例化,但是该实例的属性还未被设置,都是null。因为它的返回值是决定要不要调用postProcessPropertyValues方法的其中一个因素(因为还有一个因素是mbd.getDependencyCheck());如果该方法返回false,并且不需要check,那么postProcessPropertyValues就会被忽略不执行;如果返回true,postProcessPropertyValues就会被执行
  • postProcessPropertyValues方法对属性值进行修改(这个时候属性值还未被设置,但是我们可以修改原本该设置进去的属性值)。如果postProcessAfterInstantiation方法返回false,该方法可能不会被调用。可以在该方法内对属性值进行修改
  • 以上是关于Bean的生命周期流程-上的主要内容,如果未能解决你的问题,请参考以下文章

    Spring源码Bean的生命周期

    Bean生命周期流程--下

    Bean生命周期流程--下

    Spring中Bean的生命周期

    Spring 框架源码 Bean的生命周期全流程源码解析

    Java面试小短文Spring Bean生命周期的执行流程