spring bean的构造器参数

Posted Kobelieve

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了spring bean的构造器参数相关的知识,希望对你有一定的参考价值。

spring组件的构造器参好神奇

这里有一个接口:FruitService和两个实现类:AppleService、BananaService,假设我想在其中一个实现类实例化中获取当前Spring容器的Bean怎么办?

只需要重写该实现类的构造方法:

@Component
public class AppleService implements FruitService {

	public AppleService(List<Object> list) {
		System.out.println(list);
	}

}

list可以获取当前spring实例化好的Beans:
技术图片

我能不能只拿某个Bean呢,答案是可以的,只需要重写将Objent替换成对应的类即可:

@Component
public class AppleService implements FruitService {

	public AppleService(List<FruitService> list) {
		System.out.println(list);
	}

}

技术图片

不仅如此,还可以将参数转换成Map和Collection类型,spring也会自动帮忙处理,但是如果是非上述类型,则会在创建的时候抛出异常。

源码

由于spring源码非常深,这里直接列出处理这个人性化的地方最核心一个方法:org.springframework.beans.factory.support.DefaultListableBeanFactory#resolveMultipleBeans

	@Nullable
	private Object resolveMultipleBeans(DependencyDescriptor descriptor, @Nullable String beanName,
			@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) {

		final 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[]) {
				Comparator<Object> comparator = adaptDependencyComparator(matchingBeans);
				if (comparator != null) {
					Arrays.sort((Object[]) result, comparator);
				}
			}
			return result;
		}
		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);
			if (result instanceof List) {
				if (((List<?>) result).size() > 1) {
					Comparator<Object> comparator = adaptDependencyComparator(matchingBeans);
					if (comparator != null) {
						((List<?>) result).sort(comparator);
					}
				}
			}
			return result;
		}
		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;
		}
	}

spring会一一匹配指定类型,假如没有匹配成功,则会返回null,匹配成功但是没有数据,则会返回一个空对象。


以上是关于spring bean的构造器参数的主要内容,如果未能解决你的问题,请参考以下文章

7 -- Spring的基本用法 -- 7...

Spring4学习回顾之路04—配置Bean (中)

Spring5 解决Bean在自动装配时的歧义性

装配Spring Bean

Spring4-自动装配Beans-通过构造函数参数的数据类型按属性自动装配Bean

Spring实战bean装配的运行时值注入——属性占位符和SpEL