Spring依赖注入源码分析

Spring依赖注入

Chapter 1 Spring依赖注入源码分析

执行流程:
在这里插入图片描述

1 调用示例

/**
 * @ClassName AnnotationDependencyConstructorInjectionDemo
 * @Description 基于 Java 注解方式进行Constructor依赖注入示例
 * @Author WQ
 * @Date 2022/7/5 16:07
 * @Version 1.0
 */
public class AnnotationDependencyInjectionResolutionDemo {


    @Autowired
    private User user;
    
    @Autowired
    private Map<String, User> users;

    @Autowired
    @Lazy
    private User superUser;

    public static void main(String[] args) {
        // 获取应用上下文
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
        // XmlBeanDefinition 读取器
        XmlBeanDefinitionReader xmlBeanDefinitionReader = new XmlBeanDefinitionReader(applicationContext);
        // 依赖的上下文路径
        String xmlPath = "classpath:/META-INF/dependency-lookup-context.xml";
        // 加载 BeanDefinition
        xmlBeanDefinitionReader.loadBeanDefinitions(xmlPath);
        applicationContext.register(AnnotationDependencyInjectionResolutionDemo.class);
        // 启动容器
        applicationContext.refresh();
        AnnotationDependencyInjectionResolutionDemo demo = applicationContext.getBean(AnnotationDependencyInjectionResolutionDemo.class);

        System.out.println(demo.user);

        // 关闭容器
        applicationContext.close();
    }
}

2 DefaultListableBeanFactory#resolveDependency方法分析

DefaultListableBeanFactory#resolveDependency 解析依赖的方法

  • DependencyDescriptor descriptor 依赖的描述符
  • String requestingBeanName 需要注入的Bean名称
  • Set autowiredBeanNames 所有需要自动注入的 Bean 的名称
  • TypeConverter typeConverter 对于数组或者集合的转换器
    该方法主要判断需要注入的对象的类型,走不通的分支去注入对象
	@Override
	@Nullable
	public Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName,
			@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
        
		descriptor.initParameterNameDiscovery(getParameterNameDiscoverer());
		// 判断被注入的类是否为 Optional 类型
		if (Optional.class == descriptor.getDependencyType()) {
			return createOptionalDependency(descriptor, requestingBeanName);
		}
		// 判断被注入的类是否为 ObjectFactory 或者 ObjectFactory 等延迟加载的类型
		else if (ObjectFactory.class == descriptor.getDependencyType() ||
				ObjectProvider.class == descriptor.getDependencyType()) {
			return new DependencyObjectProvider(descriptor, requestingBeanName);
		}
		// 判断被注入的类是否为 javaxInjectProviderClass 类型
		else if (javaxInjectProviderClass == descriptor.getDependencyType()) {
			return new Jsr330Factory().createDependencyProvider(descriptor, requestingBeanName);
		}
		else {
		    // 如果是用 @Lazy 注解标注的对象,则返回 CGLIB 提升过的代理对象
			Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(
					descriptor, requestingBeanName);
			if (result == null) {
			    // 执行解析依赖的操作
				result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
			}
			return result;
		}
	}

3 DependencyDescriptor

DependencyDescriptor 是依赖的描述,该类中描述了注入对象的信息。注入类型有三种:方法注入、字段注入、构造器注入,允许其中只采用其中一种注入,但不能三种同时为空。三种注入的字段上面添加了 @Nullable 注解表明可以该字段为空,但时机上,三种注入方法必须采用其中一种,即不能同时为空。

public class DependencyDescriptor extends InjectionPoint implements Serializable {
    // 被注入的类
	private final Class<?> declaringClass;


	@Nullable // 该注解允许该参数为空
	// 方法名称 方法注入
	private String methodName; 

	@Nullable
	// 参数类型集合 构造器注入
	private Class<?>[] parameterTypes;

    // 参数位置
	private int parameterIndex;

	@Nullable
	// 字段名称 字段注入
	private String fieldName;

    // 是否是必须的,通常这个值为true
	private final boolean required;

    // 是直接加载还是懒加载,对应的为@Lazy注解,如果@lazy注解为true,该值为false
	private final boolean eager;
    
    // 嵌套层次
	private int nestingLevel = 1;

	@Nullable
	// 包含了那些类
	private Class<?> containingClass;

	@Nullable
	private transient volatile ResolvableType resolvableType;

	@Nullable
	// 类型描述 主要是类型描述的内容
	private transient volatile TypeDescriptor typeDescriptor;

}

4 doResolveDependency

DefaultListableBeanFactory#doResolveDependency 执行依赖解析的方法

@Nullable
	public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName,
			@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
        // 嵌套注入的保护点
		InjectionPoint previousInjectionPoint = ConstructorResolver.setCurrentInjectionPoint(descriptor);
		try {
		    // 是否有快捷方式
			Object shortcut = descriptor.resolveShortcut(this);
			if (shortcut != null) {
				return shortcut;
			}
            
            // 获取自动注入的类型
			Class<?> type = descriptor.getDependencyType();
			// 获取自动注入候选者解析器
			Object value = getAutowireCandidateResolver().getSuggestedValue(descriptor);
			if (value != null) {
				if (value instanceof String) {
					String strVal = resolveEmbeddedValue((String) value);
					BeanDefinition bd = (beanName != null && containsBean(beanName) ?
							getMergedBeanDefinition(beanName) : null);
					value = evaluateBeanDefinitionString(strVal, bd);
				}
				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()));
				}
			}

            // 
			Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);
			if (multipleBeans != null) {
			    // 这里解析到数据就直接返回了,不会继续往下走
				return multipleBeans;
			}

            // 根据名称、类型、描述来查找符合条件的 Bean
			Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
			if (matchingBeans.isEmpty()) {
				if (isRequired(descriptor)) {
					raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
				}
				return null;
			}

			String autowiredBeanName;
			Object instanceCandidate;
            
            // 如果候选者的数量大于一
			if (matchingBeans.size() > 1) {
			    // 确定自动注入候选者的名称
				autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor);
				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;
					}
				}
				// 从 IoC Container 中调用 beanFactory.getBean(name) 去获取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();
			}

			if (autowiredBeanNames != null) {
				autowiredBeanNames.add(autowiredBeanName);
			}
			if (instanceCandidate instanceof Class) {
			    // 如果 候选者实例是 Class 类型, 则调用 beanFactory.getBean(beanName);
				instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this);
			}
			Object result = instanceCandidate;
			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());
			}
			// 返回查找到的Bean
			return result;
		}
		finally {
			ConstructorResolver.setCurrentInjectionPoint(previousInjectionPoint);
		}
	}
	
		/**
	 * Resolve the specified bean name, as a candidate result of the matching
	 * algorithm for this dependency, to a bean instance from the given factory.
	 * <p>The default implementation calls {@link BeanFactory#getBean(String)}.
	 * Subclasses may provide additional arguments or other customizations.
	 * @param beanName the bean name, as a candidate result for this dependency
	 * @param requiredType the expected type of the bean (as an assertion)
	 * @param beanFactory the associated factory
	 * @return the bean instance (never {@code null})
	 * @throws BeansException if the bean could not be obtained
	 * @since 4.3.2
	 * @see BeanFactory#getBean(String)
	 */
	public Object resolveCandidate(String beanName, Class<?> requiredType, BeanFactory beanFactory)
			throws BeansException {

		return beanFactory.getBean(beanName);
	}

5 resolveMultipleBeans

DefaultListableBeanFactory#resolveMultipleBeans 该方法是解析 Stream、Array、Collection、Map 等类型,该方法中会提前调用 findAutowireCandidates 方法去查找符合条件的对象。

@Nullable
	private Object resolveMultipleBeans(DependencyDescriptor descriptor, @Nullable String beanName,
			@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) {
        // 注入对象的类型
		final Class<?> type = descriptor.getDependencyType();

        // 如果是 Stream 类型
		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) {
				Comparator<Object> comparator = adaptDependencyComparator(matchingBeans);
				if (comparator != null) {
					((List<?>) result).sort(comparator);
				}
			}
			return result;
		}
		// 如果对象的类型为Map
		else if (Map.class == type) {
		    // 从 descriptor 中获取解析类型并封装成一个 Map
			ResolvableType mapType = descriptor.getResolvableType().asMap();
			// 获取 Map 的 key 的类型
			Class<?> keyType = mapType.resolveGeneric(0);
			if (String.class != keyType) {
				return null;
			}
			// 获取 Map 的 value 的类型 此处为User
			Class<?> valueType = mapType.resolveGeneric(1);
			if (valueType == null) {
				return null;
			}
			// 根据 beanName、valueType、new MultiElementDescriptor(descriptor)多元素描述符来查找对象
			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;
		}
	}

6 findAutowireCandidates

DefaultListableBeanFactory#findAutowireCandidates 自动注入单个对象,找自动注入的候选者

/**
	 * Find bean instances that match the required type.
	 * Called during autowiring for the specified bean.
	 * @param beanName the name of the bean that is about to be wired
	 * @param requiredType the actual type of bean to look for
	 * (may be an array component type or collection element type)
	 * @param descriptor the descriptor of the dependency to resolve
	 * @return a Map of candidate names and candidate instances that match
	 * the required type (never {@code null})
	 * @throws BeansException in case of errors
	 * @see #autowireByType
	 * @see #autowireConstructor
	 */
	protected Map<String, Object> findAutowireCandidates(
			@Nullable String beanName, Class<?> requiredType, DependencyDescriptor descriptor) {
        
        // 获取候选者的名称
        // BeanFactoryUtils.beanNamesForTypeIncludingAncestors(ListableBeanFactory lbf, Class<?> type, boolean includeNonSingletons, boolean allowEagerInit);
        // ListableBeanFactory lbf IoC 容器
        // Class<?> type 需要注入的类型
        // boolean includeNonSingletons 是否为非单例
        // boolean allowEagerInit 是否为懒加载
		String[] candidateNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
				this, requiredType, true, descriptor.isEager());
		Map<String, Object> result = new LinkedHashMap<>(candidateNames.length);
		// 遍历已经解析的依赖
		for (Map.Entry<Class<?>, Object> classObjectEntry : this.resolvableDependencies.entrySet()) {
		    // 获取自动注入的类型
			Class<?> autowiringType = classObjectEntry.getKey();
			// requiredType是自动注入的类型,即示例中的 User 
			// autowiringType 已经解析的依赖的类型
			// 判断这两个类型是否具有继承或者这两者是否有相等
			if (autowiringType.isAssignableFrom(requiredType)) {
			    // 获取自动注入的对象
				Object autowiringValue = classObjectEntry.getValue();
				autowiringValue = AutowireUtils.resolveAutowiringValue(autowiringValue, requiredType);
				if (requiredType.isInstance(autowiringValue)) {
					result.put(ObjectUtils.identityToString(autowiringValue), autowiringValue);
					break;
				}
			}
		}
		// 遍历候选者名称
		for (String candidate : candidateNames) {
			if (!isSelfReference(beanName, candidate) && isAutowireCandidate(candidate, descriptor)) {
			    // 添加到候选者列表 result 中
				addCandidateEntry(result, candidate, descriptor, requiredType);
			}
		}
		// 如果没有找到类型相同或者具有继承关系的类
		if (result.isEmpty()) {
			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);
				}
			}
			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;
	}

7 beanNamesForTypeIncludingAncestors

BeanFactoryUtils#beanNamesForTypeIncludingAncestors
该方法的作用为从 IoC 容器中根据类型获取名称,如果当前的 IoC 容器是一个 层次性的容器,则还会递归向上查找父类中有没有符合条件的 Bean,如果找到符合条件的 Bean,最终将BeanName 合并成一个数组进行返回

/**
	 * Get all bean names for the given type, including those defined in ancestor
	 * factories. Will return unique names in case of overridden bean definitions.
	 * <p>Does consider objects created by FactoryBeans if the "allowEagerInit"
	 * flag is set, which means that FactoryBeans will get initialized. If the
	 * object created by the FactoryBean doesn't match, the raw FactoryBean itself
	 * will be matched against the type. If "allowEagerInit" is not set,
	 * only raw FactoryBeans will be checked (which doesn't require initialization
	 * of each FactoryBean).
	 * @param lbf the bean factory
	 * @param includeNonSingletons whether to include prototype or scoped beans too
	 * or just singletons (also applies to FactoryBeans)
	 * @param allowEagerInit whether to initialize <i>lazy-init singletons</i> and
	 * <i>objects created by FactoryBeans</i> (or by factory methods with a
	 * "factory-bean" reference) for the type check. Note that FactoryBeans need to be
	 * eagerly initialized to determine their type: So be aware that passing in "true"
	 * for this flag will initialize FactoryBeans and "factory-bean" references.
	 * @param type the type that beans must match
	 * @return the array of matching bean names, or an empty array if none
	 * @see ListableBeanFactory#getBeanNamesForType(Class, boolean, boolean)
	 */
	public static String[] beanNamesForTypeIncludingAncestors(
			ListableBeanFactory lbf, Class<?> type, boolean includeNonSingletons, boolean allowEagerInit) {

		Assert.notNull(lbf, "ListableBeanFactory must not be null");
		// 从 IoC 容器中根据类型获取 BeanName
		String[] result = lbf.getBeanNamesForType(type, includeNonSingletons, allowEagerInit);
		// 如果 IoC 容器是实现了HierarchicalBeanFactory(层次性的 BeanFactory )
		if (lbf instanceof HierarchicalBeanFactory) {
		    // 将 IoC 容器转换为 HierarchicalBeanFactory 层次性 BeanFactory
			HierarchicalBeanFactory hbf = (HierarchicalBeanFactory) lbf;
			// 如果当前容器的父容器也是 ListableBeanFactory
			if (hbf.getParentBeanFactory() instanceof ListableBeanFactory) {
			    // 递归调用查询父容器中的 BeanName
				String[] parentResult = beanNamesForTypeIncludingAncestors(
						(ListableBeanFactory) hbf.getParentBeanFactory(), type, includeNonSingletons, allowEagerInit);
				// 合并结果
				result = mergeNamesWithParent(result, parentResult, hbf);
			}
		}
		// 返回查询到的符合条件的名称
		return result;
	}

8 isAssignableFrom

如果是A.isAssignableFrom(B) 确定一个类(B)是不是继承来自于另一个父类(A),一个接口(A)是不是实现了另外一个接口(B),或者两个类相同。主要,这里比较的维度不是实例对象,而是类本身,因为这个方法本身就是Class类的方法,判断的肯定是和类信息相关的。

public native boolean isAssignableFrom(Class<?> cls);

class A{
}
class B extends A{
}
class C extends B{
}

public class test {
    public static void main(String[] args) {
        A a = new A();
        B b = new B();
        B b1 = new B();
        C c = new C();
        System.out.println(a.getClass().isAssignableFrom(a.getClass()));
        System.out.println(a.getClass().isAssignableFrom(b.getClass()));
        System.out.println(a.getClass().isAssignableFrom(c.getClass()));
        System.out.println(b1.getClass().isAssignableFrom(b.getClass()));

        System.out.println(b.getClass().isAssignableFrom(c.getClass()));

        System.out.println("=====================================");
        System.out.println(A.class.isAssignableFrom(a.getClass()));
        System.out.println(A.class.isAssignableFrom(b.getClass()));
        System.out.println(A.class.isAssignableFrom(c.getClass()));

        System.out.println("=====================================");
        System.out.println(Object.class.isAssignableFrom(a.getClass()));
        System.out.println(Object.class.isAssignableFrom(String.class));
        System.out.println(String.class.isAssignableFrom(Object.class));
    }
}

运行结果

true
true
true
true
true
=====================================
true
true
true
=====================================
true
true
false

9 determineAutowireCandidate

DefaultListableBeanFactory#determineAutowireCandidate 确定自动注入的候选者

/**
	 * Determine the autowire candidate in the given set of beans.
	 * <p>Looks for {@code @Primary} and {@code @Priority} (in that order).
	 * @param candidates a Map of candidate names and candidate instances
	 * that match the required type, as returned by {@link #findAutowireCandidates}
	 * @param descriptor the target dependency to match against
	 * @return the name of the autowire candidate, or {@code null} if none found
	 */
	@Nullable
	protected String determineAutowireCandidate(Map<String, Object> candidates, DependencyDescriptor descriptor) {
	    // 自动注入对象的类型
		Class<?> requiredType = descriptor.getDependencyType();
		// 确定 Primary 标注的候选者
		String primaryCandidate = determinePrimaryCandidate(candidates, requiredType);
		// 如果 Primary 存在
		if (primaryCandidate != null) {
		    // 返回 Primary 标注对象的名称
			return primaryCandidate;
		}
		String priorityCandidate = determineHighestPriorityCandidate(candidates, requiredType);
		if (priorityCandidate != null) {
			return priorityCandidate;
		}
		// Fallback
		for (Map.Entry<String, Object> entry : candidates.entrySet()) {
			String candidateName = entry.getKey();
			Object beanInstance = entry.getValue();
			if ((beanInstance != null && this.resolvableDependencies.containsValue(beanInstance)) ||
					matchesBeanName(candidateName, descriptor.getDependencyName())) {
				return candidateName;
			}
		}
		return null;
	}

10 determinePrimaryCandidate

DefaultListableBeanFactory#DefaultListableBeanFactory 确定 Primary 标注的对象

/**
	 * Determine the primary candidate in the given set of beans.
	 * @param candidates a Map of candidate names and candidate instances
	 * (or candidate classes if not created yet) that match the required type
	 * @param requiredType the target dependency type to match against
	 * @return the name of the primary candidate, or {@code null} if none found
	 * @see #isPrimary(String, Object)
	 */
	@Nullable
	protected String determinePrimaryCandidate(Map<String, Object> candidates, Class<?> requiredType) {
		String primaryBeanName = null;
		// 遍历候选者列表
		for (Map.Entry<String, Object> entry : candidates.entrySet()) {
		    // 获取候选者的名称
			String candidateBeanName = entry.getKey();
			// 获取获选者的实例
			Object beanInstance = entry.getValue();
			// 根据候选者的名称和实例判断是否为Primary = true 的对象
			if (isPrimary(candidateBeanName, beanInstance)) {
			    // 找到 primary == ture 的对象
				if (primaryBeanName != null) {
				    // 从 Bean 定义的 Map中查看这个名称是否存在
					boolean candidateLocal = containsBeanDefinition(candidateBeanName);
					// 从 Bean 定义的 Map中查看这个名称是否存在
					boolean primaryLocal = containsBeanDefinition(primaryBeanName);
					// 找到了多个 Primary 标记的对象抛出错误
					if (candidateLocal && primaryLocal) {
						throw new NoUniqueBeanDefinitionException(requiredType, candidates.size(),
								"more than one 'primary' bean found among candidates: " + candidates.keySet());
					}
					else if (candidateLocal) {
						primaryBeanName = candidateBeanName;
					}
				}
				else {
					primaryBeanName = candidateBeanName;
				}
			}
		}
		return primaryBeanName;
	}
	
		@Override
	public boolean containsBeanDefinition(String beanName) {
		Assert.notNull(beanName, "Bean name must not be null");
		return this.beanDefinitionMap.containsKey(beanName);
	}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值