Spring 5.x Source trip twenty-eight Detailed thirteen populateBean a getBean

populateBean segment 1

Before filling properties, but also to the InstantiationAwareBeanPostProcessorprocessor, and give them the opportunity for them to modify beaninstance, here it is the extension point. If the processing postProcessAfterInstantiationmethod will be issued false, it will stop filling properties, out of the loop and return, indicating that you can control whether you want to fill, but the springinternal processing of the processor does not have to deal with or to go to a custom processor extensions.

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 segments 2

Get automatic assembling mode, by default NO, if there is provided, it will be assembled according to the settings.

//获取属性值
		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 segment 3

Here will be InstantiationAwareBeanPostProcessorthe processor of the postProcessPropertiesprocessing,

//是否有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 inner class of postProcessProperties ImportAwareBeanPostProcessor

This is the front of the class if there is configured Configurationannotations will be dynamic proxy, will implement EnhancedConfigurationthe interface, there are two setBeanFactoryinterface methods, it will pass 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

Here we will deal with the front applyMergedBeanDefinitionPostProcessorshandle inject metadata annotation.

	@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

Traversing the front register InjectedElement, and then injected.

	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

For injecting property or method, but the first injection method determines whether the value has been set, will not have set injection, return directly.

		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

Property to determine whether to skip the injection, if it is time to define a given value is ignored.

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

getResourceToInjectThe method is the key, in fact, is InjectedElementthe abstract methods, subclasses have different implementation classes, such as ResourceElement, , EjbRefElement, and WebServiceRefElementof course we will focus on ResourceElementthe matter, they have other interests can be seen.

This method first determine there is no metadata annotation Lazynotes, is lazy loading, if any, would create a proxy class, the interior is a AOPproxy factory to do, said the details of the back, and then there is a getTargetproxy method, may need time to get the call. If not directly getResource.

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

CommonAnnotationBeanPostProcessor的getResource

First determine the jndiinjection, then call autowireResource, we generally is 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);
	}

autowireResourceMore critical, we revisit it later.

Well, here today, we hope to help study and understand, do not spray the Great God see, understand only their own learning, limited capacity, please excuse.

Published 235 original articles · won praise 74 · views 30000 +

Guess you like

Origin blog.csdn.net/wangwei19871103/article/details/105139638