【源码】Spring —— BeanFactory 解读 5 DefaultListableBeanFactory

前言

Spring 提供的默认最终实现类,可以发现,之前的抽象实现都没有 BeanDefinition 的相关方法(换句话说,都不是 BeanDefinitionRegistry),而 DefaultListableBeanFactory 是实现了 BeanDefinitionRegistry 接口的,因此此类也会维护和管理 BeanDefinition

因此,AbstractBeanFactory 提供的抽象方法 containsBeanDefinition getBeanDefinition 也自然由此类实现,另外还有父类 AbstractAutowireCapableBeanFactory 的抽象方法 resolveDependency 方法的实现

此外,BeanFactory 基于类型的 getBean 方法也由此类实现

本章节选取几个典型方法进行解读

BeanDefinition 相关

	@Override
	public boolean containsBeanDefinition(String beanName) {
		Assert.notNull(beanName, "Bean name must not be null");
		return this.beanDefinitionMap.containsKey(beanName);
	}

	@Override
	public BeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException {
		BeanDefinition bd = this.beanDefinitionMap.get(beanName);
		if (bd == null) {
			throw new NoSuchBeanDefinitionException(beanName);
		}
		return bd;
	}

	// ...
	

它是基于属性 Map<String, BeanDefinition> beanDefinitionMap 来维护 BeanDefinition 的,因此相关方法的属性如上

resolveDependency

	@Override
	@Nullable
	public Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName,
			@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {

		// 参数名称发现器
		descriptor.initParameterNameDiscovery(getParameterNameDiscoverer());

		/**
		 * 此处是针对不同的类型对返回值进行处理,但核心逻辑依然是收口
		 * 		到 doResolveDependency 方法
		 */
		if (Optional.class == descriptor.getDependencyType()) {
			return createOptionalDependency(descriptor, requestingBeanName);
		}
		else if (ObjectFactory.class == descriptor.getDependencyType() ||
				ObjectProvider.class == descriptor.getDependencyType()) {
			return new DependencyObjectProvider(descriptor, requestingBeanName);
		}

		/**
		 * 此分支才是我们最常用的,核心逻辑在 doResolveDependency
		 */
		else {
			Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(
					descriptor, requestingBeanName);
			if (result == null) {
				result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
			}
			return result;
		}
	}

这是很重要的一个方法,给指定 bean 的指定属性解析对应依赖:

  • 可以简单的理解为,基于给定 bean 的属性元素类型,获取对应需要被注入的实例
  • DependencyDescriptor,即对应元素(属性、方法)的依赖描述,诸如 元素信息 必须性
  • 最终逻辑收口在 doResolveDependency 方法

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 {
			// ShortcutDependencyDescriptor 处理,即缓存处理
			Object shortcut = descriptor.resolveShortcut(this);
			if (shortcut != null) {
				return shortcut;
			}

			Class<?> type = descriptor.getDependencyType();
			// 如果是 @Value 注解元素,则获取 value 值
			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);
					// SpEL 解析
					value = evaluateBeanDefinitionString(strVal, bd);
				}
				// 类型转换后返回
				TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
				try {
					return converter.convertIfNecessary(value, type, descriptor.getTypeDescriptor());
				}
				catch (UnsupportedOperationException ex) {
					
				}
			}

			/**
			 * 对于返回类型是 Array Collection Map 类型的属性,
			 * 会对基于 findAutowireCandidates 获取的实例进行类型转换后直接返回
			 */
			Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);
			if (multipleBeans != null) {
				return multipleBeans;
			}

			/**
			 * 核心方法 findAutowireCandidates:获取所有符合
			 * 		注入条件的实例
			 */
			Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);

			// 如果没有,抛出异常 expected at least 1 bean which qualifies as autowire candidate.
			if (matchingBeans.isEmpty()) {
				if (isRequired(descriptor)) {
					raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
				}
				return null;
			}

			String autowiredBeanName;
			Object instanceCandidate;

			/**
			 * 如何元素个数多余一个,则委托 determineAutowireCandidate 方法
			 * 		进行再次筛选
			 * 如果筛选结果为空,但接受元素不是集合类型,则抛出异常
			 * 如果筛选出来了,那么就最终返回
			 */
			if (matchingBeans.size() > 1) {
				autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor);
				if (autowiredBeanName == null) {
					if (isRequired(descriptor) || !indicatesMultipleBeans(type)) {
						return descriptor.resolveNotUnique(descriptor.getResolvableType(), matchingBeans);
					}
					else {
						return null;
					}
				}
				instanceCandidate = matchingBeans.get(autowiredBeanName);
			}
			else {
				Map.Entry<String, Object> entry = matchingBeans.entrySet().iterator().next();
				autowiredBeanName = entry.getKey();
				instanceCandidate = entry.getValue();
			}

			// 返回唯一备选实例
			
			return result;
		}
		finally {
			ConstructorResolver.setCurrentInjectionPoint(previousInjectionPoint);
		}
	}

这里的逻辑较长较复杂:

  • 首先会处理 @Value 注解,包括 占位符解析 SpEL表达式解析
  • 其次针对集合类型元素诸如 Map Array 等,对 findAutowireCandidates 方法返回的备选实例集合进行处理后返回
  • 而对于单个元素,若不存在备选实例则视情况抛出异常,若存在多个实例则由 determineAutowireCandidate 方法进行进一步筛选
  • findAutowireCandidates 方法即获取所有备选实例,此处的筛选逻辑主要依赖于 AutowireCandidateResolver,此处便不再深入

determineAutowireCandidate

	@Nullable
	protected String determineAutowireCandidate(Map<String, Object> candidates, DependencyDescriptor descriptor) {
		Class<?> requiredType = descriptor.getDependencyType();

		// 筛选出被 @Primary 注解修饰的实例
		String primaryCandidate = determinePrimaryCandidate(candidates, requiredType);
		if (primaryCandidate != null) {
			return primaryCandidate;
		}

		// 根据实现的 Priority 接口进行优先级过滤
		String priorityCandidate = determineHighestPriorityCandidate(candidates, requiredType);
		if (priorityCandidate != null) {
			return priorityCandidate;
		}
		
		/**
		 * 最后,如果是 resolvableDependencies 则优先返回
		 * 否则进行 name 匹配
		 */
		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;
	}

如上文提到,对于单个元素,如果筛选出多个备选实例,则有该方法进一步筛选:

  • 被注解 @Primary 修饰的实例优先
  • 基于接口 Priority 进行优先级筛选
  • 基于元素名称与 beanName 的匹配筛选

getBean

AbstractBeanFactory 中提供了基于 name 获取 bean实例 的方法实现,而通常我们最常用的基于 type 获取 bean实例 是由 DefaultListableBeanFactory 实现的

	@Override
	public <T> T getBean(Class<T> requiredType) throws BeansException {
		return getBean(requiredType, (Object[]) null);
	}

	@SuppressWarnings("unchecked")
	@Override
	public <T> T getBean(Class<T> requiredType, @Nullable Object... args) throws BeansException {
		Object resolved = resolveBean(ResolvableType.forRawClass(requiredType), args, false);
		if (resolved == null) {
			throw new NoSuchBeanDefinitionException(requiredType);
		}
		return (T) resolved;
	}

	@Nullable
	private <T> T resolveBean(ResolvableType requiredType, @Nullable Object[] args, boolean nonUniqueAsNull) {
		NamedBeanHolder<T> namedBean = resolveNamedBean(requiredType, args, nonUniqueAsNull);
		if (namedBean != null) {
			return namedBean.getBeanInstance();
		}
		
		// 尝试从 父BeanFactory 获取 ...
		
		return null;
	}
  • 可以看到,基于 type 获取 bean实例 最终是委托到 resolveNamedBean 方法的
  • NamedBeanHolder 类是一个基于 namebean实例 简易封装

resolveNamedBean

	@Nullable
	private <T> NamedBeanHolder<T> resolveNamedBean(
			ResolvableType requiredType, @Nullable Object[] args, boolean nonUniqueAsNull) throws BeansException {
			
		// 获取指定类型的所有备选 name
		String[] candidateNames = getBeanNamesForType(requiredType);

		/**
		 * 第一轮过滤:
		 * 1)不包含对应 BeanDefinition(可能是别名)
		 * 或
		 * 2)包含指定 BeanDefinition 且可注入(默认 true)
		 */
		if (candidateNames.length > 1) {
			List<String> autowireCandidates = new ArrayList<>(candidateNames.length);
			for (String beanName : candidateNames) {
				if (!containsBeanDefinition(beanName) || getBeanDefinition(beanName).isAutowireCandidate()) {
					autowireCandidates.add(beanName);
				}
			}
			if (!autowireCandidates.isEmpty()) {
				candidateNames = StringUtils.toStringArray(autowireCandidates);
			}
		}

		// 正好一个的话直接返回即可
		if (candidateNames.length == 1) {
			String beanName = candidateNames[0];
			return new NamedBeanHolder<>(beanName, (T) getBean(beanName, requiredType.toClass(), args));
		}
		
		/**
		 * 多余一个则进行筛选
		 * 1)determinePrimaryCandidate:被 @Primary 注解修饰
		 * 2)determineHighestPriorityCandidate:基于 @Priority 的优先级比较
		 * 否则默认抛出异常 NoUniqueBeanDefinitionException
		 */
		else if (candidateNames.length > 1) {
			Map<String, Object> candidates = CollectionUtils.newLinkedHashMap(candidateNames.length);
			for (String beanName : candidateNames) {
				if (containsSingleton(beanName) && args == null) {
					Object beanInstance = getBean(beanName);
					candidates.put(beanName, (beanInstance instanceof NullBean ? null : beanInstance));
				}
				else {
					candidates.put(beanName, getType(beanName));
				}
			}
			String candidateName = determinePrimaryCandidate(candidates, requiredType.toClass());
			if (candidateName == null) {
				candidateName = determineHighestPriorityCandidate(candidates, requiredType.toClass());
			}
			if (candidateName != null) {
				Object beanInstance = candidates.get(candidateName);
				if (beanInstance == null || beanInstance instanceof Class) {
					beanInstance = getBean(candidateName, requiredType.toClass(), args);
				}
				return new NamedBeanHolder<>(candidateName, (T) beanInstance);
			}
			if (!nonUniqueAsNull) {
				throw new NoUniqueBeanDefinitionException(requiredType, candidates.keySet());
			}
		}

		return null;
	}

方法略长,但实现思路较清晰:

  • 先获取指定类型的所有备选 name,如果正好一个那返回即可
  • 如果多于一个,进行筛选,筛选逻辑:唯一标注 @Primary 注解的实例优先,如果没有,则基于 @Priority 进行优先级比较,返回最高优先级的 bean实例
  • 如果没有匹配的,则抛出 NoUniqueBeanDefinitionException

registerResolvableDependency

该方法是注册一组 type -> bean实例,继而对于该类型的注入会将该实例作为备选

这就是为什么我们可以直接注入 BeanFactory Application 等实例直接使用,因为容器会
为我们注册上述依赖,代码如下:

beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
beanFactory.registerResolvableDependency(ResourceLoader.class, this);
beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
beanFactory.registerResolvableDependency(ApplicationContext.class, this);

preInstantiateSingletons

	@Override
	public void preInstantiateSingletons() throws BeansException {
		
		List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);

		// 遍历所有的 beanName,创建其中的非 Lazy 单例
		for (String beanName : beanNames) {
			RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
			if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {

				// 如果是 FactoryBean
				if (isFactoryBean(beanName)) {

					// 会先创建 FactoryBean 本身
					Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
					if (bean instanceof FactoryBean) {
						FactoryBean<?> factory = (FactoryBean<?>) bean;
						boolean isEagerInit;
						if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
							isEagerInit = AccessController.doPrivileged(
									(PrivilegedAction<Boolean>) ((SmartFactoryBean<?>) factory)::isEagerInit,
									getAccessControlContext());
						}
						else {
							isEagerInit = (factory instanceof SmartFactoryBean &&
									((SmartFactoryBean<?>) factory).isEagerInit());
						}

						/**
						 * 如果是 SmartFactoryBean 并且 SmartFactoryBean#isEagerInit == true
						 * 		时,才会创建 FactoryBean#getObject 实例
						 */
						if (isEagerInit) {
							getBean(beanName);
						}
					}
				}
				else {
					getBean(beanName);
				}
			}
		}

		// 上述单例创建完后会执行 SmartInitializingSingleton#afterSingletonsInstantiated
		for (String beanName : beanNames) {
			Object singletonInstance = getSingleton(beanName);
			if (singletonInstance instanceof SmartInitializingSingleton) {
				
				// ...
				smartSingleton.afterSingletonsInstantiated();
					
				// ...
			}
		}
	}
  • 基于容器中注册的所有 BeanDefinition,创建非 Lazysingleton
  • 对实现了 SmartInitializingSingleton 接口的上述 bean,会执行其方法 afterSingletonsInstantiated

registerSingleton

DefaultListableBeanFactory 同时也是一个 SingletonBeanRegistry,一定程度上这是它的主要角色,因此,registerSingleton 也在此处暴露出去,并进行了拓展

	@Override
	public void registerSingleton(String beanName, Object singletonObject) throws IllegalStateException {
		
		// DefaultSingletonBeanRegistry.registerSingleton 
		super.registerSingleton(beanName, singletonObject);
		
		// 记录到集合 manualSingletonNames 中
		updateManualSingletonNames(set -> set.add(beanName), set -> !this.beanDefinitionMap.containsKey(beanName));
		clearByTypeCache();
	}

总结

DefaultListableBeanFactory 作为最终实现,同时也是容器中默认使用的 BeanFactory,因此提供了很多方法,此处也仅仅是列举部分

上一篇:【源码】Spring —— BeanFactory 解读 4 关于循环依赖

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值