java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > Spring @Autowired注入集合控制顺序

Spring @Autowired注入集合时如何控制顺序

作者:Yux_o

想知道Spring @Autowired注入集合时怎么排序吗?本文深入源码,讲解AnnotationAwareOrderComparator如何根据PriorityOrdered、Ordered接口和@Order注解对List和数组排序,以及Map、Set注入的注意事项,帮你彻底搞懂集合注入顺序

一、@Autowired注入集合顺序源码分析 Spring 5.3.2

1、线程调用链

2、注入主要逻辑

//org.springframework.beans.factory.support.DefaultListableBeanFactory#resolveMultipleBeans
@Nullable
private Object resolveMultipleBeans(DependencyDescriptor descriptor, @Nullable String beanName,
		@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) {

	Class<?> type = descriptor.getDependencyType();

	if (descriptor instanceof StreamDependencyDescriptor) {
		Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
		if (autowiredBeanNames != null) {
			autowiredBeanNames.addAll(matchingBeans.keySet());
		}
		Stream<Object> stream = matchingBeans.keySet().stream()
				.map(name -> descriptor.resolveCandidate(name, type, this))
				.filter(bean -> !(bean instanceof NullBean));
		if (((StreamDependencyDescriptor) descriptor).isOrdered()) {
			stream = stream.sorted(adaptOrderComparator(matchingBeans));
		}
		return stream;
	}
	//支持数组
	else if (type.isArray()) {
		Class<?> componentType = type.getComponentType();
		ResolvableType resolvableType = descriptor.getResolvableType();
		Class<?> resolvedArrayType = resolvableType.resolve(type);
		if (resolvedArrayType != type) {
			componentType = resolvableType.getComponentType().resolve();
		}
		if (componentType == null) {
			return null;
		}
		//找到容器中匹配得实例<实例名,对象>
		Map<String, Object> matchingBeans = findAutowireCandidates(beanName, componentType,
				new MultiElementDescriptor(descriptor));
		if (matchingBeans.isEmpty()) {
			return null;
		}
		if (autowiredBeanNames != null) {
			autowiredBeanNames.addAll(matchingBeans.keySet());
		}
		//类型转换器
		TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
		//把找到的实例转换成需要的类型
		Object result = converter.convertIfNecessary(matchingBeans.values(), resolvedArrayType);
		if (result instanceof Object[]) {
			//近似看成得到一个AnnotationAwareOrderComparator外部比较器
			/**
			* 实际是得到一个OrderComparator对象 重写了compare方法 调用AnnotationAwareOrderComparator的doCompare方法
			**/
			Comparator<Object> comparator = adaptDependencyComparator(matchingBeans);
			if (comparator != null) {
				//排序**********
				Arrays.sort((Object[]) result, comparator);
			}
		}
		return result;
	}
	//支持Collection及其子类 必须为接口
	else if (Collection.class.isAssignableFrom(type) && type.isInterface()) {
		Class<?> elementType = descriptor.getResolvableType().asCollection().resolveGeneric();
		if (elementType == null) {
			return null;
		}
		//找到容器中匹配得实例<实例名,对象>
		Map<String, Object> matchingBeans = findAutowireCandidates(beanName, elementType,
				new MultiElementDescriptor(descriptor));
		if (matchingBeans.isEmpty()) {
			return null;
		}
		if (autowiredBeanNames != null) {
			autowiredBeanNames.addAll(matchingBeans.keySet());
		}
		//类型转换器
		TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
		//把找到的实例转换成需要的类型
		Object result = converter.convertIfNecessary(matchingBeans.values(), type);
		//只有是List集合 才会排序
		if (result instanceof List) {
			if (((List<?>) result).size() > 1) {
				//近似看成得到一个AnnotationAwareOrderComparator外部比较器
				/**
				* 实际是得到一个OrderComparator对象 重写了compare方法 调用AnnotationAwareOrderComparator的doCompare方法
				**/
				Comparator<Object> comparator = adaptDependencyComparator(matchingBeans);
				if (comparator != null) {
					//排序**********
					((List<?>) result).sort(comparator);
				}
			}
		}
		return result;
	}
	//支持Map类型 只能为Map
	else if (Map.class == type) {
		ResolvableType mapType = descriptor.getResolvableType().asMap();
		Class<?> keyType = mapType.resolveGeneric(0);
		if (String.class != keyType) {
			return null;
		}
		Class<?> valueType = mapType.resolveGeneric(1);
		if (valueType == null) {
			return null;
		}
		//找到容器中匹配得实例<实例名,对象>
		Map<String, Object> matchingBeans = findAutowireCandidates(beanName, valueType,
				new MultiElementDescriptor(descriptor));
		if (matchingBeans.isEmpty()) {
			return null;
		}
		if (autowiredBeanNames != null) {
			autowiredBeanNames.addAll(matchingBeans.keySet());
		}
		return matchingBeans;
	}
	else {
		return null;
	}
}

3、AnnotationAwareOrderComparator比较器核心代码

3.1、首先来看两个重要类的继承结构

AnnotationAwareOrderComparator类继承结构



PriorityOrdered类继承结构


3.2 、比较器核心代码

调用顺序

OrderComparator#doCompare
org.springframework.core.OrderComparator#getOrder(java.lang.Object, org.springframework.core.OrderComparator.OrderSourceProvider) org.springframework.core.annotation.AnnotationAwareOrderComparator#findOrder
org.springframework.core.OrderComparator#findOrder
org.springframework.core.OrderComparator#getOrder(java.lang.Object)
//org.springframework.core.OrderComparator#doCompare
private int doCompare(@Nullable Object o1, @Nullable Object o2, @Nullable OrderSourceProvider sourceProvider) {
	boolean p1 = (o1 instanceof PriorityOrdered);
	boolean p2 = (o2 instanceof PriorityOrdered);
	/**
	* PriorityOrdered接口实例和非PriorityOrdered接口实例比较PriorityOrdered实例放前面
	**/
	if (p1 && !p2) {
		return -1;
	}
	else if (p2 && !p1) {
		return 1;
	}
	
	int i1 = getOrder(o1, sourceProvider);
	int i2 = getOrder(o2, sourceProvider);
	return Integer.compare(i1, i2);
}

//org.springframework.core.OrderComparator#getOrder(java.lang.Object, org.springframework.core.OrderComparator.OrderSourceProvider)
private int getOrder(@Nullable Object obj, @Nullable OrderSourceProvider sourceProvider) {
	Integer order = null;
	if (obj != null && sourceProvider != null) {
		Object orderSource = sourceProvider.getOrderSource(obj);
		if (orderSource != null) {
			if (orderSource.getClass().isArray()) {
				for (Object source : ObjectUtils.toObjectArray(orderSource)) {
					order = findOrder(source);
					if (order != null) {
						break;
					}
				}
			}
			else {
				order = findOrder(orderSource);
			}
		}
	}
	return (order != null ? order : getOrder(obj));
}

//org.springframework.core.OrderComparator#getOrder(java.lang.Object)
protected int getOrder(@Nullable Object obj) {
	if (obj != null) {
		Integer order = findOrder(obj);
		if (order != null) {
			return order;
		}
	}
	//如果没有获取到排序值 返回返回最大排序值即放到最后
	return Ordered.LOWEST_PRECEDENCE;
}

//org.springframework.core.OrderComparator#findOrder
@Nullable
protected Integer findOrder(Object obj) {
	//得到Ordered接口中的排序值 PriorityOrdered也是Ordered子类 没实现Ordered接口接口返回null
	return (obj instanceof Ordered ? ((Ordered) obj).getOrder() : null);
}

//org.springframework.core.annotation.AnnotationAwareOrderComparator#findOrder
@Override
@Nullable
protected Integer findOrder(Object obj) {
	//调用父类Ordered接口中findOrder方法
	Integer order = super.findOrder(obj);
	//有排序值则直接返回
	if (order != null) {
		return order;
	}
	//如果为空 说明实例没有实现Ordered接口 则取类上@Order注解上获取排序值
	return findOrderFromAnnotation(obj);
}

//org.springframework.core.annotation.AnnotationAwareOrderComparator#findOrderFromAnnotation
@Nullable
private Integer findOrderFromAnnotation(Object obj) {
	AnnotatedElement element = (obj instanceof AnnotatedElement ? (AnnotatedElement) obj : obj.getClass());
	MergedAnnotations annotations = MergedAnnotations.from(element, SearchStrategy.TYPE_HIERARCHY);
	//获取@Order注解中的排序值 没有返回null
	Integer order = OrderUtils.getOrderFromAnnotations(element, annotations);
	if (order == null && obj instanceof DecoratingProxy) {
		return findOrderFromAnnotation(((DecoratingProxy) obj).getDecoratedClass());
	}
	return order;
}

3.3 、小结

下面将没有实现PriorityOrdered接口,也没实现Ordered接口,也没有加@Order注解的类实例叫做 三无实例

OrderComparator类实现的功能:根据PriorityOrdered和Ordered接口中的排序值进行排序。总结一哈大概有以下情况:

  1. PriorityOrdered实例 和 非PriorityOrdered实例,PriorityOrdered实例放前面
  2. PriorityOrdered实例 和 PriorityOrdered实例,根据getOrder接口方法得到排序值比较
  3. Ordered实例 和 Ordered实例,根据getOrder接口方法得到排序值比较
  4. 三无实例 和 三无实例,三无实例排序值为Integer最大值,所以两个比较顺序不变
  5. Ordered实例 和 三无实例,三无实例排序值为Integer最大值,所有getOrder接口方法得到排序值和Integer最大值比较

AnnotationAwareOrderComparator类实现的功能:AnnotationAwareOrderComparator类是继承OrderComparator类的,所以在上面OrderComparator类功能的基础上,扩展了如果没有实现PriorityOrdered和Ordered接口的情况,从@Order注解中获取排序值。

总结一哈大概有以下情况:

  1. PriorityOrdered实例 和 非PriorityOrdered实例,PriorityOrdered实例放前面
  2. PriorityOrdered实例 和 PriorityOrdered实例,根据getOrder方法得到排序值比较
  3. Ordered实例 和 Ordered实例,根据getOrder方法得到排序值比较
  4. @Order实例 和 @Order实例, 根据@Order中的排序值比较
  5. 三无实例 和 三无实例,三无实例排序值为Integer最大值,所以两个比较顺序不变
  6. Ordered实例 和 三无实例,三无实例排序值为Integer最大值,所有getOrder接口方法得到排序值和Integer最大值比较
  7. Ordered实例 和 @Order实例,根据getOrder方法得到排序值和@Order中的排序值比较
  8. @Order实例 和 三无实例,三无实例排序值为Integer最大值,所有@Order中的排序值和Integer最大值比较

关于一个实现了PriorityOrdered接口、Ordered接口、加了@Order注解的类中取排序值的优先级:

通过源码可知,如果实现了PriorityOrdered接口,那么该类实例只能和同样实现了PriorityOrdered接口比较才是通过排序值进行比较的,不然和非实现PriorityOrdered接口的类实例比较,实现了PriorityOrdered接口直接拍前面(不会管排序值大小)。

如果不满足上面,就会先从Ordered接口中取排序值,没有实现Ordered接口的话,就会从@Order注解获取排序值,如果没有加@Order注解,排序值默认为Integer最大值。

二、@Autowired能注入的集合类型及集合中顺序

1、数组

看过源码可知是根据AnnotationAwareOrderComparator外部比较器进行排序的,所以支持PriorityOrdered接口 、Ordered接口、@Order排序

2、Collection及其子类且必须为接口

看过源码源码可知只有当为List及其子接口时才会进行排序,是根据AnnotationAwareOrderComparator比较器进行排序,所以支持PriorityOrdered接口 、Ordered接口、@Order排序

那么如果注入Set集合要排序怎么办呢,我们阔以注入到SortedSet集合中,在把要注入的实例类型实现Comparable接口实现自定义排序

3、只能是Map,不能是其子类

看过源码可知,Map是不能进行排序的,而且只能注入Map集合中,不能是Map子类。

Key为实例在容器中的名称,Value为该实例。

三、总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

您可能感兴趣的文章:
阅读全文