spring5.3 七:依赖注入源码分析中

依赖注入源码分析中

依赖注入底层原理流程图: https://www.processon.com/view/link/5f899fa5f346fb06e1d8f570

@Autowired自动注入

上一篇分析@Autowired是如何自动注入的,首先通过遍历构建成bean的类的字段和方法找到注入点,这个过程在BeanDefinition后置处理中完成,找到后保存起来。到了属性注入阶段把注入点拿出来,通过inject方法赋值,inject方法最终赋值是通过反射进行赋值。但是在inject中如何找到属性对应的bean没有分析,下面接着来分析。
value = resolveFieldValue(field, bean, beanName);arguments = resolveMethodArguments(method, bean, beanName);分别是找属性对应的bean和找方法参数对应的bean。
属性如何找bean

@Nullable
		private Object resolveFieldValue(Field field, Object bean, @Nullable String beanName) {
			//构建注入点的描述器
			DependencyDescriptor desc = new DependencyDescriptor(field, this.required);
			desc.setContainingClass(bean.getClass());
			Set<String> autowiredBeanNames = new LinkedHashSet<>(1);
			Assert.state(beanFactory != null, "No BeanFactory available");
			//获取类型转化器
			TypeConverter typeConverter = beanFactory.getTypeConverter();
			Object value;
			try {
				//核心方法
				value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);
			}
			catch (BeansException ex) {
				throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(field), ex);
			}
			synchronized (this) {
				if (!this.cached) {
					Object cachedFieldValue = null;
					if (value != null || this.required) {
						cachedFieldValue = desc;
						// 注册一下beanName依赖了autowiredBeanNames
						registerDependentBeans(beanName, autowiredBeanNames);
						if (autowiredBeanNames.size() == 1) {
							String autowiredBeanName = autowiredBeanNames.iterator().next();
							if (beanFactory.containsBean(autowiredBeanName) &&
									beanFactory.isTypeMatch(autowiredBeanName, field.getType())) {
								// 构造一个ShortcutDependencyDescriptor作为缓存,保存了当前filed所匹配的autowiredBeanName,而不是对应的bean对象(考虑原型bean)
								cachedFieldValue = new ShortcutDependencyDescriptor(
										desc, autowiredBeanName, field.getType());
							}
						}
					}
					this.cachedFieldValue = cachedFieldValue;
					this.cached = true;
				}
			}
			return value;
		}
	}

首先通过属性构造一个注入点的描述器DependencyDescriptor,通过核心方法value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter)获取到对应的bean进行返回。
DependencyDescriptor
spring5.3 七:依赖注入源码分析中_第1张图片
DependencyDescriptor包含了方法、属性的元数据信息(方法类型,名称,属性类型,属性名称等)。
方法参数如何找Bean

@Nullable
		private Object[] resolveMethodArguments(Method method, Object bean, @Nullable String beanName) {
			//获取方法参数的个数
			int argumentCount = method.getParameterCount();
			//构造出参数的数组
			Object[] arguments = new Object[argumentCount];
			//DependencyDescriptor注入点描述器 就是把需要属性注入的方法、字段封装到一个类当中
			DependencyDescriptor[] descriptors = new DependencyDescriptor[argumentCount];
			Set<String> autowiredBeans = new LinkedHashSet<>(argumentCount);
			Assert.state(beanFactory != null, "No BeanFactory available");
			TypeConverter typeConverter = beanFactory.getTypeConverter();

			// 遍历每个方法参数,找到匹配的bean对象
			for (int i = 0; i < arguments.length; i++) {
				//表示方法的第i个参数  就是封装了一下
				MethodParameter methodParam = new MethodParameter(method, i);
				// this.required 就是@autowire require的值
				// 二次封装
				DependencyDescriptor currDesc = new DependencyDescriptor(methodParam, this.required);
				currDesc.setContainingClass(bean.getClass());
				descriptors[i] = currDesc;
				try {
					//核心方法  找参数对应的bean
					Object arg = beanFactory.resolveDependency(currDesc, beanName, autowiredBeans, typeConverter);
					if (arg == null && !this.required) {
						arguments = null;
						break;
					}
					//把找到的bean放到数组当中
					arguments[i] = arg;
				}
				catch (BeansException ex) {
					throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(methodParam), ex);
				}
			}
			synchronized (this) {
				if (!this.cached) {
					if (arguments != null) {
						DependencyDescriptor[] cachedMethodArguments = Arrays.copyOf(descriptors, arguments.length);
						registerDependentBeans(beanName, autowiredBeans);
						if (autowiredBeans.size() == argumentCount) {
							Iterator<String> it = autowiredBeans.iterator();
							Class<?>[] paramTypes = method.getParameterTypes();
							for (int i = 0; i < paramTypes.length; i++) {
								String autowiredBeanName = it.next();
								if (beanFactory.containsBean(autowiredBeanName) &&
										beanFactory.isTypeMatch(autowiredBeanName, paramTypes[i])) {
									cachedMethodArguments[i] = new ShortcutDependencyDescriptor(
											descriptors[i], autowiredBeanName, paramTypes[i]);
								}
							}
						}
						this.cachedMethodArguments = cachedMethodArguments;
					}
					else {
						this.cachedMethodArguments = null;
					}
					this.cached = true;
				}
			}
			return arguments;
		}
	}

这个过程也差不多最终也是根据Object arg = beanFactory.resolveDependency(currDesc, beanName, autowiredBeans, typeConverter);找到bean。不过是属性zhaobean还是方法参数找bean最终都是通过beanFactory.resolveDependency方法找到bean。
beanFactory.resolveDependency(currDesc, beanName, autowiredBeans, typeConverter)传入注入点描述器、beanName、集合、类型转换器。

public Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName,
			@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
		// 用来获取方法入参名字的
		// getParameterNameDiscoverer() 采用反射 或者本地变量表
		descriptor.initParameterNameDiscovery(getParameterNameDiscoverer());
		// 所需要的类型是Optional
		if (Optional.class == descriptor.getDependencyType()) {
			return createOptionalDependency(descriptor, requestingBeanName);
		}
		// 所需要的的类型是ObjectFactory,或ObjectProvider
		else if (ObjectFactory.class == descriptor.getDependencyType() ||
				ObjectProvider.class == descriptor.getDependencyType()) {
			return new DependencyObjectProvider(descriptor, requestingBeanName);
		}
		else if (javaxInjectProviderClass == descriptor.getDependencyType()) {
			return new Jsr330Factory().createDependencyProvider(descriptor, requestingBeanName);
		}
		else {
			//判断属性或者set方法上有没有@Lazy注解 如果有则构造一个代理对象并返回 真正使用该代理对象时才进行类型筛选Bean
			// 如果没有返回null
			Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(
					descriptor, requestingBeanName);
			if (result == null) {
				// descriptor表示某个属性或某个set方法
				// requestingBeanName表示正在进行依赖注入的Bean
				//核心方法
				result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
			}
			return result;
		}
	}

这个过程对注入点的类型进行判断做出对应处理,重点来看对@Lazy注解的处理,如果注入点标记有@Lazy那么注入的是代理对象,而不是真正的bean对象。如果没有@Lazy返回null,然后通过doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);找到bean赋值给result 然后方法返回result 。

public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName,
			@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
		InjectionPoint previousInjectionPoint = ConstructorResolver.setCurrentInjectionPoint(descriptor);
		try {
			// 如果当前descriptor之前做过依赖注入了,则可以直接取shortcut了,相当于缓存
			Object shortcut = descriptor.resolveShortcut(this);
			if (shortcut != null) {
				return shortcut;
			}
			//获取类型  有可能是字段的类型 也可能是方法参数的类型
			Class<?> type = descriptor.getDependencyType();
			// 获取@Value所指定的值 例如@Value("aaa") 就是获取到aaa
			Object value = getAutowireCandidateResolver().getSuggestedValue(descriptor);
			//对@value注解的处理
			if (value != null) {
				//如果是String类型
				if (value instanceof String) {
					// 占位符填充(${})
					String strVal = resolveEmbeddedValue((String) value);
					BeanDefinition bd = (beanName != null && containsBean(beanName) ?
							getMergedBeanDefinition(beanName) : null);
					// 解析Spring表达式(#{})
					value = evaluateBeanDefinitionString(strVal, bd);
				}
				// 将value转化为descriptor所对应的类型
				TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
				try {
					return converter.convertIfNecessary(value, type, descriptor.getTypeDescriptor());
				}
				catch (UnsupportedOperationException ex) {
					// A custom TypeConverter which does not support TypeDescriptor resolution...
					return (descriptor.getField() != null ?
							converter.convertIfNecessary(value, type, descriptor.getField()) :
							converter.convertIfNecessary(value, type, descriptor.getMethodParameter()));
				}
			}
			// 如果descriptor所对应的类型是数组、Map这些,就把匹配的bean全都放入到数组、map等当中
			Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);
			if (multipleBeans != null) {
				return multipleBeans;
			}
			// 找到所有符合类型的Bean记录到map当中
			// 核心方法 findAutowireCandidates 如何根据类型找到对应bean的过程
			Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
			if (matchingBeans.isEmpty()) {
				// required为true,抛异常
				if (isRequired(descriptor)) {
					raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
				}
				return null;
			}
			String autowiredBeanName;
			Object instanceCandidate;
			//如果找到的bean大于一个 进一步的筛选  否则执行else的方法
			if (matchingBeans.size() > 1) {
				// 根据类型找到了多个Bean,进一步筛选出某一个bean
				//返回beanName 后续从map中将具体的bean找出来
				// 大致过程: 先判断有bean有没有@Primary  在判断优先级 最后根据名称找bean
				autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor);
				//这个if表示 如果通过上面的方法 找不到合适bean 再判断isRequired属性 如果为true 则抛出异常
				if (autowiredBeanName == null) {
					if (isRequired(descriptor) || !indicatesMultipleBeans(type)) {
						return descriptor.resolveNotUnique(descriptor.getResolvableType(), matchingBeans);
					}
					else {
						// In case of an optional Collection/Map, silently ignore a non-unique case:
						// possibly it was meant to be an empty collection of multiple regular beans
						// (before 4.3 in particular when we didn't even look for collection beans).
						return null;
					}
				}
				//根据beanName获取具体的bean
				instanceCandidate = matchingBeans.get(autowiredBeanName);
			}
			else {
				// We have exactly one match.
				Map.Entry<String, Object> entry = matchingBeans.entrySet().iterator().next();
				autowiredBeanName = entry.getKey();
				instanceCandidate = entry.getValue();
			}

			// 记录匹配过的beanName
			if (autowiredBeanNames != null) {
				autowiredBeanNames.add(autowiredBeanName);
			}
			// 有可能筛选出来的是某个bean已经实例化了  也有可能是的bean的class类型,如果是class类型此处就进行实例化
			if (instanceCandidate instanceof Class) {
				//具体就是调用getBean方法
				instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this);
			}
			Object result = instanceCandidate;
			//当使用@bean 定义了一个bean  但是 return null 的时候 就属于NullBean 类型
			//如果符合这个类型 会判断isRequired属性 如果为true 就会抛异常
			if (result instanceof NullBean) {
				if (isRequired(descriptor)) {
					raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
				}
				result = null;
			}
			if (!ClassUtils.isAssignableValue(type, result)) {
				throw new BeanNotOfRequiredTypeException(autowiredBeanName, type, instanceCandidate.getClass());
			}
			return result;
		}
		finally {
			ConstructorResolver.setCurrentInjectionPoint(previousInjectionPoint);
		}
	}

这个方法中大致过程分为以下几步

  1. 先获取注入点的类型,然后对标记@value注解的注入点进行处理。
  2. 处理完后判断注入点类型是不是list、map、数组这些,如果是找到所有符合类型的bean放入到集合当中。直接返回。如果不是上面这些类型,那么这接着往下执行。
  3. 通过findAutowireCandidates(beanName, type, descriptor)方法找到所有符合类型的bean。这个后面分析
  4. 如果找不到符合的bean,并且该属性的isRequired为true,那么报错找不到bean。如果找到的bean只有一个,记录到String autowiredBeanNameObject instanceCandidate;中,如果找到的bean大于1个执行determineAutowireCandidate(matchingBeans, descriptor)
  5. determineAutowireCandidate(matchingBeans, descriptor)方法就是筛选bean。首先判断bean有没有@Primary注解,有就返回。如果没有,判断@Priority 取优先级最高的bean。注意这里的优先级是@Priority不是@Order。如果还是没有,接着通过beanName进行和属性的名称进行匹配,找到符合的bean返回。返回同样记录autowiredBeanNameinstanceCandidate
  6. 进一步判断返回的bean是真正实例化过的bean呢还是NullBean还是Class类型。如果是Class类型就会调用getBean方法进行实例化。最终返回这个bean。

接下来主要分析findAutowireCandidates(beanName, type, descriptor)这个方法如何找到bean。
findAutowireCandidates

protected Map<String, Object> findAutowireCandidates(
			@Nullable String beanName, Class<?> requiredType, DependencyDescriptor descriptor) {
		// 从BeanFactory中找出和requiredType所匹配的beanName,
		// 仅仅是beanName,这些bean不一定经过了实例化,只有到最终确定某个Bean了,如果这个Bean还没有实例化才会真正进行实例化
		//beanNamesForTypeIncludingAncestors 大致过程:在本容器和父容器中找bean
		// 怎么找: 通过遍历所有beanName 获取对应RootBeanDefinition 根据RootBeanDefinition 做一系列判断
		String[] candidateNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
				this, requiredType, true, descriptor.isEager());
		Map<String, Object> result = CollectionUtils.newLinkedHashMap(candidateNames.length);

		// 根据类型从resolvableDependencies中匹配Bean
		// resolvableDependencies中存放的是类型:Bean对象,比如BeanFactory.class:BeanFactory对象,在Spring启动时设置
		for (Map.Entry<Class<?>, Object> classObjectEntry : this.resolvableDependencies.entrySet()) {
			Class<?> autowiringType = classObjectEntry.getKey();
			if (autowiringType.isAssignableFrom(requiredType)) {
				Object autowiringValue = classObjectEntry.getValue();
				autowiringValue = AutowireUtils.resolveAutowiringValue(autowiringValue, requiredType);
				if (requiredType.isInstance(autowiringValue)) {
					//把匹配的bean类型加入到result中  这个result就是上面找到符合的beanName的map
					result.put(ObjectUtils.identityToString(autowiringValue), autowiringValue);
					break;
				}
			}
		}
		//遍历所有匹配的beanName  然后根据条件把符合的beanName  加入到result当中
		for (String candidate : candidateNames) {
			// 如果不是自己,则判断该candidate到底能不能用来进行自动注入
			//!isSelfReference(beanName, candidate) :判断是不是自己注入自己  如果不是接着判断
			// isAutowireCandidate(candidate, descriptor) :判断这个bean能不能依赖注入  这里涉及到责任链模式
			if (!isSelfReference(beanName, candidate) && isAutowireCandidate(candidate, descriptor)) {
				addCandidateEntry(result, candidate, descriptor, requiredType);
			}
		}

		// 为空要么是真的没有匹配的,要么是匹配的自己
		if (result.isEmpty()) {
			// 需要匹配的类型是不是Map、数组之类的
			boolean multiple = indicatesMultipleBeans(requiredType);
			// Consider fallback matches if the first pass failed to find anything...
			DependencyDescriptor fallbackDescriptor = descriptor.forFallbackMatch();
			for (String candidate : candidateNames) {
				if (!isSelfReference(beanName, candidate) && isAutowireCandidate(candidate, fallbackDescriptor) &&
						(!multiple || getAutowireCandidateResolver().hasQualifier(descriptor))) {
					addCandidateEntry(result, candidate, descriptor, requiredType);
				}
			}

			// 匹配的是自己,被自己添加到result中
			if (result.isEmpty() && !multiple) {
				// Consider self references as a final pass...
				// but in the case of a dependency collection, not the very same bean itself.
				for (String candidate : candidateNames) {
					if (isSelfReference(beanName, candidate) &&
							(!(descriptor instanceof MultiElementDescriptor) || !beanName.equals(candidate)) &&
							isAutowireCandidate(candidate, fallbackDescriptor)) {
						addCandidateEntry(result, candidate, descriptor, requiredType);
					}
				}
			}
		}
		return result;
	}

大致过程:

  1. 找出BeanFactory中类型为type的所有的Bean的名字,注意是名字,而不是Bean对象,因为我们可以根据BeanDefinition就能判断和当前type是不是匹配,不用生成Bean对象
    根据类型找beanName的底层流程:https://www.processon.com/view/link/6135bb430e3e7412ecd5d1f2

  2. 把resolvableDependencies中key为type的对象找出来并添加到result中

  3. 遍历根据type找出的beanName,判断当前beanName对应的Bean是不是能够被自动注入
    先判断beanName对应的BeanDefinition中的autowireCandidate属性,如果为false,表示不能用来进行自动注入,如果为true则继续进行判断
    spring5.3 七:依赖注入源码分析中_第2张图片

  4. 判断当前type是不是泛型,如果是泛型是会把容器中所有的beanName找出来的,如果是这种情况,那么在这一步中就要获取到泛型的真正类型,然后进行匹配,如果当前beanName和当前泛型对应的真实类型匹配,那么则继续判断

  5. 如果当前DependencyDescriptor上存在@Qualifier注解,那么则要判断当前beanName上是否定义了Qualifier,并且是否和当前DependencyDescriptor上的Qualifier相等,相等则匹配

  6. 经过上述验证之后,当前beanName才能成为一个可注入的,添加到result中

整个依赖注入的执行流程:https://www.processon.com/view/link/5f8fdfa8e401fd06fd984f20

上面有个重要的点是isAutowireCandidate方法。它是接口AutowireCandidateResolver的默认方法,是用来判断@bean属性autowireCandidate
在这里插入图片描述
但是isAutowireCandidate执行的其实是它的子类,是一个责任链模式
在这里插入图片描述

	@Override
	public boolean isAutowireCandidate(String beanName, DependencyDescriptor descriptor)
			throws NoSuchBeanDefinitionException {
		//该方法的顶级接口AutowireCandidateResolver 对isAutowireCandidate有默认方法 用来判断@bean属性autowireCandidate
		//大致过程 :这里一个责任链模式
		// SimpleAutowireCandidateResolver  从BeanDefinition层面判断BeanDefinition的属性isAutowireCandidate  符不符合依赖注入
		// GenericTypeAwareAutowireCandidateResolver  从泛型层面  判断 符不符合依赖注入
		// QualifierAnnotationAutowireCandidateResolver 判断@Qualifier注解的值 根据这个值去找对饮的bean
		//调用过程就是 一开始会调用 QualifierAnnotationAutowireCandidateResolver
		// 然后QualifierAnnotationAutowireCandidateResolver 调用父类 GenericTypeAwareAutowireCandidateResolver
		// 然后GenericTypeAwareAutowireCandidateResolver 继续调用父类 SimpleAutowireCandidateResolver
		return isAutowireCandidate(beanName, descriptor, getAutowireCandidateResolver());
	}

getAutowireCandidateResolver() 得到的是ContextAnnotationAutowireCandidateResolver
在这里插入图片描述
所以会先调QualifierAnnotationAutowireCandidateResolver的isAutowireCandidate方法。
GenericTypeAwareAutowireCandidateResolver 用来判断泛型
QualifierAnnotationAutowireCandidateResolver 用来判断 @Qualifier

到此@Autowired自动注入分析到此结束,下篇分析@Resource和进行依赖注入的总结

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