Spring 5.x 源码之旅二十八getBean详解十三populateBean一

populateBean分段1

在填充属性前,还会给InstantiationAwareBeanPostProcessor的处理器处理,给他们机会让他们去修改bean实例,这里也是扩展点。如果处理postProcessAfterInstantiation方法会发false,那就会停止属性填充,跳出循环并返回,说明可以控制是否要进行填充,但是spring内部的处理器不会有处理,要处理还是要自定义去扩展处理器。

boolean continueWithPropertyPopulation = true;//是否让InstantiationAwareBeanPostProcessor继续执行
		// 在填充前还可以用InstantiationAwareBeanPostProcessors来修改bean
		if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {//非合成的
			for (BeanPostProcessor bp : getBeanPostProcessors()) {
				if (bp instanceof InstantiationAwareBeanPostProcessor) {
					InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
					if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
						continueWithPropertyPopulation = false;//停止处理
						break;
					}
				}
			}
		}
		if (!continueWithPropertyPopulation) {//如果停止处理就返回
			return;
		}

populateBean分段2

获取自动装配模式,默认是NO,如果有设置了,就会根据设置来进行装配。

//获取属性值
		PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);
		//获取自动装配模式,默认是no
		int resolvedAutowireMode = mbd.getResolvedAutowireMode();
		if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
			MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
			// Add property values based on autowire by name if applicable.
			if (resolvedAutowireMode == AUTOWIRE_BY_NAME) {
				autowireByName(beanName, mbd, bw, newPvs);
			}
			// Add property values based on autowire by type if applicable.
			if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
				autowireByType(beanName, mbd, bw, newPvs);
			}
			pvs = newPvs;
		}

populateBean分段3

这里会进行InstantiationAwareBeanPostProcessor处理器的postProcessProperties处理,

//是否有InstantiationAwareBeanPostProcessors
		boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
		boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);

		PropertyDescriptor[] filteredPds = null;
		if (hasInstAwareBpps) {
			if (pvs == null) {//创建PropertyValues
				pvs = mbd.getPropertyValues();
			}
			for (BeanPostProcessor bp : getBeanPostProcessors()) {//继续后置处理器处理
				if (bp instanceof InstantiationAwareBeanPostProcessor) {
					InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
					PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
					if (pvsToUse == null) {
						if (filteredPds == null) {
							filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
						}
						pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
						if (pvsToUse == null) {
							return;
						}
					}
					pvs = pvsToUse;
				}
			}
		}
		

ConfigurationClassPostProcessor内部类ImportAwareBeanPostProcessor的postProcessProperties

这个就是前面如果配置类有Configuration注解,会进行动态代理,会实现EnhancedConfiguration接口,里面有个setBeanFactory接口方法,会传入beanFactory

@Override
		public PropertyValues postProcessProperties(@Nullable PropertyValues pvs, Object bean, String beanName) {
			// Inject the BeanFactory before AutowiredAnnotationBeanPostProcessor's
			// postProcessProperties method attempts to autowire other configuration beans.
			if (bean instanceof EnhancedConfiguration) {
				((EnhancedConfiguration) bean).setBeanFactory(this.beanFactory);
			}
			return pvs;
		}

CommonAnnotationBeanPostProcessor的postProcessProperties

这里就处理我们前面applyMergedBeanDefinitionPostProcessors处理注入注解元数据。

	@Override
	public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
		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;
	}

InjectionMetadata的inject

遍历前面注册的InjectedElement,然后进行注入。

	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()) {
			for (InjectedElement element : elementsToIterate) {
				if (logger.isTraceEnabled()) {
					logger.trace("Processing injected element of bean '" + beanName + "': " + element);
				}
				element.inject(target, beanName, pvs);
			}
		}
	}

InjectedElement的inject

进行属性或者方法注入,但是方法注入前会判断是否已经有设置值了,有设置就不会注入,直接返回了。

		protected void inject(Object target, @Nullable String requestingBeanName, @Nullable PropertyValues pvs)
				throws Throwable {

			if (this.isField) {//属性注入
				Field field = (Field) this.member;
				ReflectionUtils.makeAccessible(field);
				field.set(target, getResourceToInject(target, requestingBeanName));
			}
			else {
				if (checkPropertySkipping(pvs)) {
					return;
				}
				try {//方法注入
					Method method = (Method) this.member;
					ReflectionUtils.makeAccessible(method);
					method.invoke(target, getResourceToInject(target, requestingBeanName));
				}
				catch (InvocationTargetException ex) {
					throw ex.getTargetException();
				}
			}
		}

checkPropertySkipping

判断是否要略过属性注入,如果是定义的时候给定值了就忽略。

protected boolean checkPropertySkipping(@Nullable PropertyValues pvs) {
			Boolean skip = this.skip;
			if (skip != null) {
				return skip;
			}
			if (pvs == null) {
				this.skip = false;
				return false;
			}
			synchronized (pvs) {
				skip = this.skip;
				if (skip != null) {
					return skip;
				}
				if (this.pd != null) {
					if (pvs.contains(this.pd.getName())) {
						// 给定了值了就忽略,直接返回
						this.skip = true;
						return true;
					}
					else if (pvs instanceof MutablePropertyValues) {//如果是可变的话,就注册到处理过的属性集合里
						((MutablePropertyValues) pvs).registerProcessedProperty(this.pd.getName());
					}
				}
				this.skip = false;
				return false;
			}
		}

ResourceElement的getResourceToInject

getResourceToInject是关键的方法,其实是InjectedElement的抽象方法,子类有不同的实现类,比如ResourceElementEjbRefElementWebServiceRefElement,当然我们就关注ResourceElement啦,其他自己有兴趣可以看。

这个方法首先判断注释元数据有没有Lazy注解,也就是懒加载,有的话会创建一个代理类,内部是用AOP代理工厂做的,细节后面说,然后有个getTarget代理方法,可以在需要时候调用获取。如果不是就直接getResource

@Override
		protected Object getResourceToInject(Object target, @Nullable String requestingBeanName) {
			return (this.lazyLookup ? buildLazyResourceProxy(this, requestingBeanName) :
					getResource(this, requestingBeanName));
		}

CommonAnnotationBeanPostProcessor的getResource

先判断jndi的注入,然后才调用autowireResource,我们一般就是autowireResource

protected Object getResource(LookupElement element, @Nullable String requestingBeanName)
			throws NoSuchBeanDefinitionException {

		if (StringUtils.hasLength(element.mappedName)) {
			return this.jndiFactory.getBean(element.mappedName, element.lookupType);
		}
		if (this.alwaysUseJndiLookup) {
			return this.jndiFactory.getBean(element.name, element.lookupType);
		}
		if (this.resourceFactory == null) {
			throw new NoSuchBeanDefinitionException(element.lookupType,
					"No resource factory configured - specify the 'resourceFactory' property");
		}
		return autowireResource(this.resourceFactory, element, requestingBeanName);
	}

autowireResource比较关键,我们后面再讲吧。

好了,今天就到这里了,希望对学习理解有帮助,大神看见勿喷,仅为自己的学习理解,能力有限,请多包涵。

发布了235 篇原创文章 · 获赞 74 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/wangwei19871103/article/details/105139638