Bean生命周期流程--下

Posted 热爱编程的大忽悠

tags:

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

Bean生命周期流程--下


引言

生命周期流程-上我们还剩下两个重要的方法未讲解,分别是: populateBean和initializeBean,本文我们一起来看一下。


AbstractAutowireCapableBeanFactory#populateBean实现依赖注入

	protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) 
		...
		
		boolean continueWithPropertyPopulation = true;

		//给InstantiationAwareBeanPostProcessors最后一次机会在属性注入前修改Bean的属性值
		//具体通过调用postProcessAfterInstantiation方法,如果调用返回false,表示不必继续进行依赖注入,直接返回
		if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) 
			for (BeanPostProcessor bp : getBeanPostProcessors()) 
				if (bp instanceof InstantiationAwareBeanPostProcessor) 
					InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
				
					//postProcessAfterInstantiation 这个方法返回true,后面的处理器才会继续执行,单反返回false,后面的就不会再执行了
					//并且continueWithPropertyPopulation 打上标记表示false,也就是说后面的属性复制就不会再执行了
					if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) 
						continueWithPropertyPopulation = false;
						break;
					
				
			
		
		
		// 处理器若告知说不用继续赋值了,那就以处理器的结果为准即可
		if (!continueWithPropertyPopulation) 
			return;
		

		//pvs是一个MutablePropertyValues实例,里面实现了PropertyValues接口,提供属性的读写操作实现,同时可以通过调用构造函数实现深拷贝
		//本例中,我们的helloServiceImpl的Bean定义里,pvs为null
		PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);

		//根据Bean配置的依赖注入方式完成注入,默认是0,即不走以下逻辑,所有的依赖注入都需要在xml(或者@Bean中)文件中有显式的配置
		//如果设置了相关的依赖装配方式,会遍历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, mbd, bw, newPvs);
			

			// Add property values based on autowire by type if applicable.
			// 根据类型进行注入(见下)
			if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) 
				autowireByType(beanName, mbd, bw, newPvs);
			
			//结合注入后的配置,覆盖当前配置
			pvs = newPvs;
		

		// 显然hasInstAwareBpps=true,
		boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
		//是否进行依赖检查  默认值就是None  所以此处返回false,表示不需要依赖检查(关于依赖检查的4种模式,建议使用@Required来显示控制)
		//@Required注解作用于BeanSetter方法上,用于检查一个Bean的属性的值在配置期间是否被赋予或设置(populated)
		boolean needsDepCheck = (mbd.getDependencyCheck() != RootBeanDefinition.DEPENDENCY_CHECK_NONE);

		if (hasInstAwareBpps || needsDepCheck) 
			if (pvs == null) 
				pvs = mbd.getPropertyValues();
			
			// 过滤出所有需要进行依赖检查的属性编辑器
			PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);

			// 在这个节点上:调用了InstantiationAwareBeanPostProcessor#postProcessPropertyValues方法,
			// 若返回null,整个populateBean方法就结束了=============
			if (hasInstAwareBpps) 
				for (BeanPostProcessor bp : getBeanPostProcessors()) 
					if (bp instanceof InstantiationAwareBeanPostProcessor) 
						InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
						// 关于postProcessPropertyValues的实现,有几个处理器是非常关键的:
						// 比如AutowiredAnnotationBeanPostProcessor、CommonAnnotationBeanPostProcessor等等,且看下面的分解
						pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
						// 若返回null,Spring表示你已经属性值都设置好了,那他也不再管了
						if (pvs == null) 
							return;
						
					
				
			
			// 显然,现在大多数情况下,都不会在check这个了
			if (needsDepCheck) 
				checkDependencies(beanName, mbd, filteredPds, pvs);
			
		

		// 将pvs上所有的属性填充到BeanWrapper对应的Bean实例中
		// 注意:这一步完成结束后为止。我们的HelloServiceImpl这个Bean依赖的parent,还只是RuntimeBeanReference类型,还并不是真实的Parent这个Bean
		//在Spring的解析段,其它容器中是没有依赖的Bean的实例的,因此这个被依赖的Bean需要表示成RuntimeBeanReferenc对象,并将它放到BeanDefinition的MutablePropertyValues中。
		if (pvs != null) 
			applyPropertyValues(beanName, mbd, bw, pvs);
		
		
	

先看看autowireByName和autowireByType这两步是怎么实现的:

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

		//根据bw的PropertyDescriptors,遍历出所有可写的(即set方法存在),存在于BeanDefinition里的PropertyValues,且不是简单属性的属性名
		//简单属性的判定参照下面方法,主要涵盖基本类型及其包装类,Number,Date等=============
		String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
		for (String propertyName : propertyNames) 
			
			// 显然,只有容器里存在的,才能根据这个名称注册进去。
			//注意,这里存在,有点意思:含有Bean,或者Bean定义等等都算
			/** @Override
			public boolean containsBean(String name) 
				String beanName = transformedBeanName(name);
				// 首先工厂里必须有单例Bean,或者bean定义
				// 然后还必须不是BeanFactory(不是&打头),或者是FactoryBean  就算是包含这个Bean的
				if (containsSingleton(beanName) || containsBeanDefinition(beanName)) 
					return (!BeanFactoryUtils.isFactoryDereference(name) || isFactoryBean(name));
				
				
				// Not found -> check parent.  看看父容器里有木有
				BeanFactory parentBeanFactory = getParentBeanFactory();
				return (parentBeanFactory != null && parentBeanFactory.containsBean(originalBeanName(name)));
			 */
			
			// 再说明一下containsLocalBean这个方法,和containsBean的区别在于它只在自己的容器里找,不去父容器里找,其余的一样
			if (containsBean(propertyName)) 
				// 注意:此处找到依赖了,调用了getBean(),所以即使你现在仅仅只是Bean定义,那么会被创建实例对象
				Object bean = getBean(propertyName);
				pvs.add(propertyName, bean);
				// 注册依赖关系
				// 此处需要知道的是:Spring中使用dependentBeanMap和dependenciesForBeanMap来管理这些Bean的依赖关系:
				//Map<String, Set<String>> dependentBeanMap:存放着当前Bean被引用的Bean的集合
				//Map<String, Set<String>> dependenciesForBeanMap:存放的则是当前Bean所依赖的Bean的集合
				//依赖注入的具体实现是在BeanWrapperImpl类中的setPropertyValue方法里=======================
				registerDependentBean(propertyName, beanName);
				if (logger.isDebugEnabled()) 
					logger.debug("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");
				
			
		
	


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

		// 类型转换器,如果没有指定,就用BeanWrapper这个转换器
		TypeConverter converter = getCustomTypeConverter();
		if (converter == null) 
			converter = bw;
		

		Set<String> autowiredBeanNames = new LinkedHashSet<>(4);
		String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
		for (String propertyName : propertyNames) 
			try 
				PropertyDescriptor pd = bw.getPropertyDescriptor(propertyName);
				// Don't try autowiring by type for type Object: never makes sense,
				// even if it technically is a unsatisfied, non-simple property.
				//如果是Object类型不进行装配==============
				if (Object.class != pd.getPropertyType()) 
					// 获取相关的写方法参数
					MethodParameter methodParam = BeanUtils.getWriteMethodParameter(pd);
					// Do not allow eager init for type matching in case of a prioritized post-processor.
					// 看看实例是否实现了PriorityOrdered接口,若没有实现  就稍后点加载吧-----
					boolean eager = !PriorityOrdered.class.isInstance(bw.getWrappedInstance());
					DependencyDescriptor desc = new AutowireByTypeDependencyDescriptor(methodParam, eager);

					// 这里会根据传入desc里的入参类型,作为依赖装配的类型
					// 再根据这个类型在BeanFacoty中查找所有类或其父类相同的BeanName
					// 最后根据BeanName获取或初始化相应的类,然后将所有满足条件的BeanName填充到autowiredBeanNames中。
					Object autowiredArgument = resolveDependency(desc, beanName, autowiredBeanNames, converter);
					if (autowiredArgument != null) 
						pvs.add(propertyName, autowiredArgument);
					

					// 需要注入的依赖都拿到后,就开始注册这些依赖吧
					for (String autowiredBeanName : autowiredBeanNames) 
						// 一样的 这里注册这些依赖
						registerDependentBean(autowiredBeanName, beanName);
					
					autowiredBeanNames.clear();
				
			 catch (BeansException ex) 
				throw new UnsatisfiedDependencyException(mbd.getResourceDescription(), beanName, propertyName, ex);
			
		
	

AutowiredAnnotationBeanPostProcessor、CommonAnnotationBeanPostProcessor#postProcessPropertyValues实现注解给属性赋值:

从上面看到了,Bean已经解析拿到了注解的一些元信息,因此此处就调用一些处理器的postProcessPropertyValues方法,来给赋值了:

//AutowiredAnnotationBeanPostProcessor:这里就是解析该Bean的Autowired信息,然后给inject进去
	@Override
	public PropertyValues postProcessPropertyValues(
			PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeanCreationException 

		InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
		try 
			metadata.inject(bean, beanName, pvs);
		 catch (BeanCreationException ex) 
			throw ex;
		 catch (Throwable ex) 
			throw new BeanCreationException(beanName, "Injection of autowired dependencies failed", ex);
		
		return pvs;
	
	
//CommonAnnotationBeanPostProcessor:逻辑和上面一毛一样,它处理的JSR-250的注解,比如@Resource
	@Override
	public PropertyValues postProcessPropertyValues(
			PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException 

		InjectionMetadata metadata = findResourceMetadata(beanName, bean.getClass(), pvs);
		try 
			metadata.inject(bean, beanName, pvs);
		 catch (Throwable ex) 
			throw new BeanCreationException(beanName, "Injection of resource dependencies failed", ex);
		
		return pvs;
	
	
//RequiredAnnotationBeanPostProcessor:它就是去校验,标注了@Required注解的,必须是是存在这个Bean的
	@Override
	public PropertyValues postProcessPropertyValues(
			PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException 

		if (!this.validatedBeanNames.contains(beanName)) 
			if (!shouldSkip(this.beanFactory, beanName)) 
				List<String> invalidProperties = new ArrayList<>();
				for (PropertyDescriptor pd : pds) 
					if (isRequiredProperty(pd) && !pvs.contains(pd.getName())) 
						invalidProperties.add(pd.getName());
					
				
				if (!invalidProperties.isEmpty()) 
					throw new BeanInitializationException(buildExceptionMessage(invalidProperties, beanName));
				
			
			this.validatedBeanNames.add(beanName);
		
		return pvs;
	

InjectionMetadata#inject处理依赖注入:

	public void inject(Object target, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable 
		Collection<InjectedElement> checkedElements = this.checkedElements;
		Collection<InjectedElement> elementsToIterate =
				(checkedElements != null ? checkedElements : this.injectedElements);
		if (!elementsToIterate.isEmpty()) 
			boolean debug = logger.isDebugEnabled();
			for (InjectedElement element : elementsToIterate) 
				if (debug) 
					logger.debug("Processing injected element of bean '" + beanName + "': " + element);
				
				// 主要的方法,还是在InjectedElement#inject里
				element.inject(target, beanName, pvs);
			
		
	

InjectedElement实现如下:

这里我们就以最常用的AutowiredFieldElement为例讲解(它是一个普通内部类,为private的):

		@Override
		protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable 
			// 拿到这个字段名
			Field field = (Field) this.member;
			Object value;
			// 大多数情况下,这里都是false
			if (this.cached) 
				value = resolvedCachedArgument(beanName, this.cachedFieldValue);
			 else 
				DependencyDescriptor desc = new DependencyDescriptor(field, this.required);
				desc.setContainingClass(bean.getClass());
				Set<String> autowiredBeanNames = new LinkedHashSet<>(1);
				Assert.state(beanFactory != null, "No BeanFactory available");
				// 转换器,没有手动注册,默认都是SimpleTypeConverter===============
				TypeConverter typeConverter = beanFactory.getTypeConverter();
				try 
					// 把当前bean所依赖的这个Bean解析出来(从Spring容器里面拿,或者别的地方获取吧~~~)
					value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);
				 catch (BeansException ex) 
					throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(field), ex);
				
				synchronized (this) 
					if (!this.cached) 
						// 如果已经拿到了这个Bean实例,
						if (value != null || this.required) 
							this.cachedFieldValue = desc;
								
							// 把该Bean的依赖关系再注册一次
							registerDependentBeans(beanName, autowiredBeanNames);
							
							// 因为是按照类型注入,所以肯定只能指导一个这个的依赖Bean,否则上面解析就已经报错了
							if (autowiredBeanNames.size() == 1) 
								String autowiredBeanName = autowiredBeanNames.iterator().next();
								// 这里是来处理放置缓存的字段值
								if (beanFactory.containsBean(autowiredBeanName) &&
										beanFactory.isTypeMatch(autowiredBeanName, field.getType())) 
									this.cachedFieldValue = new ShortcutDependencyDescriptor(
											desc, autowiredBeanName, field.getType());
								
							
						 else 
							this.cachedFieldValue = null;
						
						this.cached = true;
					
				
			
			// 给该对象的该字段赋值。注意这里makeAccessible设置为true了,所以即使你的字段是private的也木有关系哦~~~
			if (value != null) 
				ReflectionUtils.makeAccessible(field);
				field.set(bean, value);
			
		
	


initializeBean进行Bean的初始化工作

上面步骤已经完成了Bean的属性的赋值工作,接下里就进行Bean的一些初始化工作,其中包括:

1:Bean后置处理器初始化

2:Bean的一些初始化方法的执行init-method等等

3:Bean的实现的声明周期相关接口的属性注入

	protected Object initializeBean(final String beanName, fin

以上是关于Bean生命周期流程--下的主要内容,如果未能解决你的问题,请参考以下文章

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

浅谈Spring中Bean的生命周期

Spring的Bean初始化过程和生命周期

Spring核心技术——Spring中Bean的生命周期

spring生命周期

如何记忆 Spring Bean 的生命周期