spring5.3 六:依赖注入源码分析上

文章目录

  • spring5.3 六:依赖注入源码分析上
    • spring的自动注入
    • @Autowired自动注入

spring5.3 六:依赖注入源码分析上

之前分析了bean的生命周期各个阶段,下面针对自动注入和属性填充这个阶段进行详细分析。先来看下这部分源码

protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
		if (bw == null) {
			if (mbd.hasPropertyValues()) {
				throw new BeanCreationException(
						mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
			}
			else {
				// Skip property population phase for null instance.
				return;
			}
		}

		// Give any InstantiationAwareBeanPostProcessors the opportunity to modify the
		// state of the bean before properties are set. This can be used, for example,
		// to support styles of field injection.
		// 实例化之后,属性设置之前
		if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
			for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
				if (!bp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
					return;
				}
			}
		}
		//这个if 会根据配置的AUTOWIRE_BY_NAME 还是 AUTOWIRE_BY_TYPE 进行属性注入
		//但是这跟AUTOWIRE注解没有关系  一般来说也不会进入到这个方法中 基本可以忽略
		//PropertyValues 是RootBeanDefinition的一个属性
		PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);
		int resolvedAutowireMode = mbd.getResolvedAutowireMode();
		if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
			// MutablePropertyValues是PropertyValues具体的实现类
			MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
			// Add property values based on autowire by name if applicable.
			if (resolvedAutowireMode == AUTOWIRE_BY_NAME) {
				//大致过程:找到bean当中需要属性注入的属性  然后记录到RootBeanDefinition的PropertyValues属性中
				autowireByName(beanName, mbd, bw, newPvs);
			}
			// Add property values based on autowire by type if applicable.
			if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
				//和上面ByName方法类似
				autowireByType(beanName, mbd, bw, newPvs);
			}
			pvs = newPvs;
		}

		boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
		boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);

		PropertyDescriptor[] filteredPds = null;
		if (hasInstAwareBpps) {
			if (pvs == null) {
				pvs = mbd.getPropertyValues();
			}
			//从这里开始处理@Autowired和@Resource
			// 处理@Autowired 的是AutowiredAnnotationBeanPostProcessor
			// 处理@Resource 的是CommonAnnotationBeanPostProcessor
			//它们都是InstantiationAwareBeanPostProcessor的实现类
			//开始遍历InstantiationAwareBeanPostProcessor这个接口的实现类
			for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
				// 这里会调用AutowiredAnnotationBeanPostProcessor的postProcessProperties()方法,会直接给对象中的属性赋值
				// AutowiredAnnotationBeanPostProcessor在调用postProcessProperties()之前会先调用postProcessMergedBeanDefinition方法
				//AutowiredAnnotationBeanPostProcessor 不仅实现了InstantiationAwareBeanPostProcessor 也实现了MergedBeanDefinitionPostProcessor
				//而postProcessMergedBeanDefinition 是MergedBeanDefinitionPostProcessor 提供的接口
				// 而MergedBeanDefinitionPostProcessor.postProcessMergedBeanDefinition是处理合并后的BeanDefinition,
				// 也就是在在实例化后这个步骤前进行调用,那么自然也就在属性赋值前就已经调用了
				// AutowiredAnnotationBeanPostProcessor内部并不会处理pvs,直接返回了
				PropertyValues pvsToUse = bp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
				if (pvsToUse == null) {
					if (filteredPds == null) {
						filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
					}
					pvsToUse = bp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
					if (pvsToUse == null) {
						return;
					}
				}
				pvs = pvsToUse;
			}
		}
		if (needsDepCheck) {
			if (filteredPds == null) {
				filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
			}
			checkDependencies(beanName, mbd, filteredPds, pvs);
		}

		// 如果当前Bean中的BeanDefinition中设置了PropertyValues,那么最终将是PropertyValues中的值,覆盖@Autowired
		if (pvs != null) {
			//进行属性赋值
			applyPropertyValues(beanName, mbd, bw, pvs);
		}
	}

这段代码主要分为两个部分,一个部分是spring自己的自动注入,就是这个if if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE)。另一部分是注解的形式例如@Autowired和@Resource。
先来看第一部分

spring的自动注入

这一部分的内容都在if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE)这个if当中,这部分的代码和@Autowired和@Resource无关,什么时候会执行这部分的代码呢?如下图
spring5.3 六:依赖注入源码分析上_第1张图片
这种方式已经过期了。稍微了解就好。以BY_NAME作为例子,那么就会进入到autowireByName(beanName, mbd, bw, newPvs);这个方法中

protected void autowireByName(
			String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {
		// 获取当前Bean中能进行自动注入的属性名
		String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
		// 遍历每个属性名,并去获取Bean对象,并设置到pvs中
		for (String propertyName : propertyNames) {
			if (containsBean(propertyName)) {
				//通过getBean方法通过名称获取到对应的bean
				Object bean = getBean(propertyName);
				//将找到的bean对象保存到pvs当中 并没有直接赋值  这个对象是上面getBean方法返回的
				// 比如说有个User对象需要注入 那么getBean返回的就是user对象 但是并没有直接赋值而是保存起来
				pvs.add(propertyName, bean);
				// 记录一下propertyName对应的Bean被beanName给依赖了
				registerDependentBean(propertyName, beanName);
				if (logger.isTraceEnabled()) {
					//忽略
			}
			else {
				//忽略
			}
		}
	}

protected String[] unsatisfiedNonSimpleProperties(AbstractBeanDefinition mbd, BeanWrapper bw) {
		Set<String> result = new TreeSet<>();
		PropertyValues pvs = mbd.getPropertyValues();
		//属性描述 set get方法的属性相关信息  比如说 set get方法名  属性名等等
		PropertyDescriptor[] pds = bw.getPropertyDescriptors();
		// 什么样的属性能进行自动注入?
		// 1.该属性有对应的set方法   pd.getWriteMethod() != null
		// 2.没有在ignoredDependencyTypes中
		// 3.如果该属性对应的set方法是实现的某个接口中所定义的,那么接口没有在ignoredDependencyInterfaces中
		// 4.属性类型不是简单类型,比如int、Integer、int[]    !BeanUtils.isSimpleProperty(pd.getPropertyType())
		// 5.BeanDefinition中的PropertyValues 中不包含这个属性 !pvs.contains(pd.getName()) 如果包含了说明之前人为的进行赋值操作
		for (PropertyDescriptor pd : pds) {
			if (pd.getWriteMethod() != null && !isExcludedFromDependencyCheck(pd) && !pvs.contains(pd.getName()) &&
					!BeanUtils.isSimpleProperty(pd.getPropertyType())) {
				result.add(pd.getName());
			}
		}
		return StringUtils.toStringArray(result);
	}

这部分内容就是说当类型设置为Autowire.BY_NAME时,就会进入autowireByName方法,然后通过unsatisfiedNonSimpleProperties方法找到那些属性是需要自动注入的,说白了就是找set方法,set后面的名称就是属性名称,遍历所有找到的名称通过getBean方法获取对应的bean然后放入到RootBeanDefinition。
autowireByType也类似,找到所有需要自动注入的属性名称后在找到对应的类型,然后根据类型找到对应的bean放入到RootBeanDefinition中。最后真正赋值的操作是applyPropertyValues(beanName, mbd, bw, pvs);这部分。

@Autowired自动注入

@Autowired注解可以写在:

  • 属性上:先根据属性类型去找Bean,如果找到多个再根据属性名确定一个
  • 构造方法上:先根据方法参数类型去找Bean,如果找到多个再根据参数名确定一个
  • set方法上:先根据方法参数类型去找Bean,如果找到多个再根据参数名确定一个

从开头的populateBean源码来看@Autowired和@Resource的自动注入根据InstantiationAwareBeanPostProcessor的子类来实现的。

@Autowired实现的子类是AutowiredAnnotationBeanPostProcessor
@Resource实现的子类是CommonAnnotationBeanPostProcessor

AutowiredAnnotationBeanPostProcessor实现了SmartInstantiationAwareBeanPostProcessorMergedBeanDefinitionPostProcessor等接口,其中MergedBeanDefinitionPostProcessor的postProcessMergedBeanDefinition方法在BeanDefinition后置处理是就执行。InstantiationAwareBeanPostProcessor的postProcessProperties方法就是在这个阶段执行,也就是说先执行postProcessMergedBeanDefinition方法。

@Override
	public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
		//找注入点
		//大致过程:根据beanName 找到类对象 对类对象处理 找到符合条件的属性和方法
		//把找到的注入点缓存起来
		InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null);
		metadata.checkConfigMembers(beanDefinition);
	}
//findAutowiringMetadata的核心代码是buildAutowiringMetadata(clazz)
private InjectionMetadata buildAutowiringMetadata(final Class<?> clazz) {
		//判断这个类需不需要找注入点 想String这种类型就不需要找注入点
		if (!AnnotationUtils.isCandidateClass(clazz, this.autowiredAnnotationTypes)) {
			return InjectionMetadata.EMPTY;
		}
		List<InjectionMetadata.InjectedElement> elements = new ArrayList<>();
		Class<?> targetClass = clazz;
		//这个do while 中分为两个大步骤
		do {
			final List<InjectionMetadata.InjectedElement> currElements = new ArrayList<>();
			// 1.遍历targetClass中的所有Field 每个Field执行lambda
			ReflectionUtils.doWithLocalFields(targetClass, field -> {
				// field上是否存在@Autowired、@Value、@Inject中的其中一个
				MergedAnnotation<?> ann = findAutowiredAnnotation(field);
				if (ann != null) {
					// ann != null 说明这个field有 上面三个注解之一
					// 继续判断 如果这个field是static类型的 那么filed不是注入点,不会进行自动注入
					//为什么静态不注入  从原型bean角度考虑
					if (Modifier.isStatic(field.getModifiers())) {
						if (logger.isInfoEnabled()) {
							logger.info("Autowired annotation is not supported on static fields: " + field);
						}
						return;
					}

					// 专门处理@Autowired的required的值
					boolean required = determineRequiredStatus(ann);
					//把这个注入点封装成AutowiredFieldElement 添加到currElements中
					currElements.add(new AutowiredFieldElement(field, required));
				}
			});

			// 2.遍历targetClass中的所有Method 每个方法执行lambda
			ReflectionUtils.doWithLocalMethods(targetClass, method -> {
				//判断是不是桥接方法 然后对桥接方法的处理 过滤调桥接方法 这跟泛型有关 不管啦
				Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);
				if (!BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) {
					return;
				}
				// method上是否存在@Autowired、@Value、@Inject中的其中一个
				MergedAnnotation<?> ann = findAutowiredAnnotation(bridgedMethod);
				if (ann != null && method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) {
					// static method不是注入点,不会进行自动注入
					if (Modifier.isStatic(method.getModifiers())) {
						if (logger.isInfoEnabled()) {
							logger.info("Autowired annotation is not supported on static methods: " + method);
						}
						return;
					}
					// set方法最好有入参 没有入参也会调到
					if (method.getParameterCount() == 0) {
						if (logger.isInfoEnabled()) {
							logger.info("Autowired annotation should only be used on methods with parameters: " +
									method);
						}
					}
					//同样解析@Autowired的required的值
					boolean required = determineRequiredStatus(ann);
					PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);
					//把这个注入点封装成AutowiredMethodElement 添加到currElements中
					currElements.add(new AutowiredMethodElement(method, required, pd));
				}
			});
			//把所有符合上面条件的Feild 和 method 放入到elements 中
			elements.addAll(0, currElements);
			//然后遍历父类 如果没有父类 那么while条件就不满足 退出循环
			targetClass = targetClass.getSuperclass();
		}
		while (targetClass != null && targetClass != Object.class);
		return InjectionMetadata.forElements(elements, clazz);
	}

	@Nullable
	private MergedAnnotation<?> findAutowiredAnnotation(AccessibleObject ao) {
		MergedAnnotations annotations = MergedAnnotations.from(ao);
		//判断获取到注解符不符合autowiredAnnotationTypes ,autowiredAnnotationTypes这是个集合
		// 在创建AutowiredAnnotationBeanPostProcessor的时候 会调用AutowiredAnnotationBeanPostProcessor的构造方法
		// 这个构造方法就会对autowiredAnnotationTypes 进行赋值 传入@Autowired @Value @Inject
		for (Class<? extends Annotation> type : this.autowiredAnnotationTypes) {
			MergedAnnotation<?> annotation = annotations.get(type);
			if (annotation.isPresent()) {
				//return 就表示了只要找到上面三个注解中某一个就会直接返回
				return annotation;
			}
		}
		return null;
	}

总的来说在BeanDefinition后置处理的阶段会先执行AutowiredAnnotationBeanPostProcessorpostProcessMergedBeanDefinition方法。这个方法主要是找注入点(被@vaule、@Autowired标注的属性和方法)。是怎么找的呢?
过滤掉String、Integer等简单的类型。遍历每个类型的属性和方法通过findAutowiredAnnotation找到注入点。把所有注入点都找到封装成一个对象放入到list中。
到了属性自动注入阶段执行AutowiredAnnotationBeanPostProcessorpostProcessProperties方法。

public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
		// 找注入点(所有被@Autowired注解了的Field或Method)
		// 把在BeanDefinition后置处理的阶段找到的注入点在拿出来
		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;
	}

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) {
				element.inject(target, beanName, pvs);
			}
		}
	}

在这里插入图片描述
第一个是给属性赋值的,第二个是给方法赋值的
AutowiredFieldElement

@Override
		protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
			Field field = (Field) this.member;
			Object value;
			if (this.cached) {
				try {
					value = resolvedCachedArgument(beanName, this.cachedFieldValue);
				}
				catch (NoSuchBeanDefinitionException ex) {
					// Unexpected removal of target bean for cached argument -> re-resolve
					value = resolveFieldValue(field, bean, beanName);
				}
			}
			else {
				// 核心方法 根据filed从BeanFactory中查到的匹配的Bean对象
				value = resolveFieldValue(field, bean, beanName);
			}
			// 反射给filed赋值
			if (value != null) {
				ReflectionUtils.makeAccessible(field);
				field.set(bean, value);
			}
		}

AutowiredMethodElement

		@Override
		protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
			//当前bean的BeanDefinition的PropertyValues属性 有没有当前注入点的值  大概是这个意思吧
			//  没太搞懂 只是个判断 不管了
			if (checkPropertySkipping(pvs)) {
				return;
			}
			Method method = (Method) this.member;
			Object[] arguments;
			if (this.cached) {
				try {
					arguments = resolveCachedArguments(beanName);
				}
				catch (NoSuchBeanDefinitionException ex) {
					// Unexpected removal of target bean for cached argument -> re-resolve
					arguments = resolveMethodArguments(method, bean, beanName);
				}
			}
			else {
				//找方法参数  核心方法
				arguments = resolveMethodArguments(method, bean, beanName);
			}
			//反射调用方法赋值
			if (arguments != null) {
				try {
					ReflectionUtils.makeAccessible(method);
					method.invoke(bean, arguments);
				}
				catch (InvocationTargetException ex) {
					throw ex.getTargetException();
				}
			}
		}

通过上述的inject方法最后都是通过反射进行赋值。到此依赖注入部分就分析完了,但是如何根据属性找到具体的bean和如何根据方法找到对应的参数下篇在分析。

你可能感兴趣的:(源码学习,spring,java)