【源码】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
类是一个基于name
的bean实例
简易封装
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
,创建非Lazy
的singleton
- 对实现了
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
,因此提供了很多方法,此处也仅仅是列举部分