概述
一、resolveDependency
在上一节最后,Spring将与获取指定相匹配的所有bean,其实现就在BeanFactory的resolveDependency中,下面是DefaultListableBeanFactory中实现:
public Object resolveDependency(DependencyDescriptor descriptor, String requestingBeanName,
Set<String> autowiredBeanNames, TypeConverter typeConverter) throws BeansException {
descriptor.initParameterNameDiscovery(getParameterNameDiscoverer());
//对于Java8中Optional类的处理
if (javaUtilOptionalClass == descriptor.getDependencyType()) {
return new OptionalDependencyFactory().createOptionalDependency(descriptor, requestingBeanName);
}
//对于前面讲到的提早曝光的ObjectFactory的特殊处理
else if (ObjectFactory.class == descriptor.getDependencyType() ||
ObjectProvider.class == descriptor.getDependencyType()) {
return new DependencyObjectProvider(descriptor, requestingBeanName);
}
//javaxInjectProviderClass的特殊处理
else if (javaxInjectProviderClass == descriptor.getDependencyType()) {
return new Jsr330ProviderFactory().createDependencyProvider(descriptor, requestingBeanName);
}
else {
//如果字段上带有@Lazy注解,表示进行懒加载
//Spring不会立即创建注入属性的实例,而是生成代理对象,来代替实例
Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(
descriptor, requestingBeanName);
if (result == null) {
//通用处理逻辑
result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
}
return result;
}
}
在上面代码中,Spring主要是先对特殊类型进行处理,如果依赖的属性是需要懒加载的话,还对生成代理对象来满足要求,最后才是通用逻辑的处理:
public Object doResolveDependency(DependencyDescriptor descriptor, String beanName,
Set<String> autowiredBeanNames, TypeConverter typeConverter) throws BeansException {
InjectionPoint previousInjectionPoint = ConstructorResolver.setCurrentInjectionPoint(descriptor);
try {
//Spring在第一次创建依赖的bean时,会保存该bena的beanName作为shortcut
//在第二次创建时,就可以直接根据beanName调用getBean方法,不需要再根据类型来重新查询一遍
Object shortcut = descriptor.resolveShortcut(this);
if (shortcut != null) {
return shortcut;
}
//注入属性的类型
Class<?> type = descriptor.getDependencyType();
//处理@Value注解-------------------------------------
//获取@Value中的value属性
Object value = getAutowireCandidateResolver().getSuggestedValue(descriptor);
if (value != null) {
//解析value
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());
//如果需要会进行类型转换后返回结果
return (descriptor.getField() != null ?
converter.convertIfNecessary(value, type, descriptor.getField()) :
converter.convertIfNecessary(value, type, descriptor.getMethodParameter()));
}
//-------------------------------------
//对数组、容器类型的处理
//因为是数组或容器,Sprng可以直接把符合类型的bean都注入到数组或容器中,处理逻辑是:
//1.确定容器或数组的组件类型
//2.调用findAutowireCandidates方法,获取与组件类型匹配的Map(beanName -> bean实例)
//3.将符合beanNames添加到autowiredBeanNames中
Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);
if (multipleBeans != null) {
return multipleBeans;
}
//对非数组、容器对象的处理
//获取所有类型匹配的Map(beanName -> bean实例)
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
//结果为空
if (matchingBeans.isEmpty()) {
//如果配置了required属性为true(默认值也是true)的话,抛出异常
if (descriptor.isRequired()) {
raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
}
return null;
}
String autowiredBeanName;
Object instanceCandidate;
//如果类型匹配的bean不止一个,Spring需要进行筛选,筛选失败的话抛出异常
if (matchingBeans.size() > 1) {
autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor);
if (autowiredBeanName == null) {
if (descriptor.isRequired() || !indicatesMultipleBeans(type)) {
return descriptor.resolveNotUnique(type, matchingBeans);
}
else {
return null;
}
}
instanceCandidate = matchingBeans.get(autowiredBeanName);
}
else {
//只有一个bean与类型匹配,那么直接使用该bean
Map.Entry<String, Object> entry = matchingBeans.entrySet().iterator().next();
autowiredBeanName = entry.getKey();
instanceCandidate = entry.getValue();
}
if (autowiredBeanNames != null) {
autowiredBeanNames.add(autowiredBeanName);
}
//如果获取到instanceCandidate是Class类型
//那么还需要beanFactory.getBean(autowiredBeanName, instanceCandidate)来获取bean的实例
//否则直接返回bean
return (instanceCandidate instanceof Class ?
descriptor.resolveCandidate(autowiredBeanName, type, this) : instanceCandidate);
}
finally {
ConstructorResolver.setCurrentInjectionPoint(previousInjectionPoint);
}
}
上面代码的处理过程:
- Spring注入依赖后会保存依赖的beanName,作为下次注入相同属性的捷径。如果存在捷径的话,直接通过保存的beanName获取bean实例
- 对@Value注解的处理。如果存在,会获取并解析value值
- 对数组或容器类型的处理。如果是数组或容器类型的话,Spring可以将所有与目标类型匹配的bean实例都注入进去,不需要判断。
- 获取数组或容器单个组件的类型
- 调用findAutowireCandidates方法,获取与组件类型匹配的Map(beanName -> bean实例)
- 保存类型匹配的beanNames
- 非数组、容器类型的处理
- 调用findAutowireCandidates方法,获取与组件类型匹配的Map(beanName -> bean实例)
- 如果类型匹配的结果为多个,需要进行筛选:Spring源码分析:多个bean同时满足注入条件时,spring的选择
- 如果筛选结果不为空,或者只有一个bean类型匹配,就直接使用该bean
二、搜索类型匹配的bean列表
根据注解进行依赖注入的主要工作,就是根据标注的字段的类型来搜索符合的bean,并将类型匹配的bean注入到字段中。而搜索bean的工作在findAutowireCandidates方法中实现:
protected Map<String, Object> findAutowireCandidates(
String beanName, Class<?> requiredType, DependencyDescriptor descriptor) {
//获取类型匹配的bean的beanName列表
String[] candidateNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
this, requiredType, true, descriptor.isEager());
//存放结果的Map(beanName -> bena实例)
Map<String, Object> result = new LinkedHashMap<String, Object>(candidateNames.length);
//如果查找的类型是特殊类型或其子类的话,也将保存好的特殊类型的实例放到结果集中
for (Class<?> autowiringType : this.resolvableDependencies.keySet()) {
if (autowiringType.isAssignableFrom(requiredType)) {
Object autowiringValue = this.resolvableDependencies.get(autowiringType);
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)) {
addCandidateEntry(result, candidate, descriptor, requiredType);
}
}
//结果集为空 && 注入属性是非数组、容器类型
//如果条件满足,Spring会放宽注入条件的限制
if (result.isEmpty() && !indicatesMultipleBeans(requiredType)) {
// FallbackMatch:放宽对泛型类型的验证
DependencyDescriptor fallbackDescriptor = descriptor.forFallbackMatch();
for (String candidate : candidateNames) {
if (!isSelfReference(beanName, candidate) && isAutowireCandidate(candidate, fallbackDescriptor)) {
addCandidateEntry(result, candidate, descriptor, requiredType);
}
}
if (result.isEmpty()) {
// 如果结果还是为空,Spring会将自引用添加到结果中
for (String candidate : candidateNames) {
if (isSelfReference(beanName, candidate) &&
(!(descriptor instanceof MultiElementDescriptor) || !beanName.equals(candidate)) &&
isAutowireCandidate(candidate, fallbackDescriptor)) {
addCandidateEntry(result, candidate, descriptor, requiredType);
}
}
}
}
return result;
}
代码步骤:
- 将获取类型匹配的Bean工作交给BeanFactoryUtils.beanNamesForTypeIncludingAncestors。该方法除了当前beanFactory还会递归对父parentFactory进行查找
- 如果注入类型是特殊类型或其子类,会将特殊类型的实例添加到结果
- 对结果进行筛选
- BeanDefinition的autowireCandidate属性,表示是否允许该bena注入到其他bean中,默认为true
- 泛型类型的匹配,如果存在的话
- Qualifier注解。如果存在Qualifier注解的话,会直接比对Qualifier注解中指定的beanName。需要注意的是,Spring处理自己定义的Qualifier注解,还支持javax.inject.Qualifier注解
- 如果筛选后,结果为空,Spring会放宽筛选条件,再筛选一次
1.BeanFactoryUtils.beanNamesForTypeIncludingAncestors
public static String[] beanNamesForTypeIncludingAncestors(
ListableBeanFactory lbf, Class<?> type, boolean includeNonSingletons, boolean allowEagerInit) {
//通过ListableBeanFactory的getBeanNamesForType方法来获取类型匹配的beanName列表
String[] result = lbf.getBeanNamesForType(type, includeNonSingletons, allowEagerInit);
//如果当前BeanFactory是HierarchicalBeanFactory,即支持父BeanFactory的功能
//Spring会对其父BeanFactory进行搜索
if (lbf instanceof HierarchicalBeanFactory) {
HierarchicalBeanFactory hbf = (HierarchicalBeanFactory) lbf;
//对父BeanFactory搜索的前提:父BeanFactory也是ListableBeanFactory
if (hbf.getParentBeanFactory() instanceof ListableBeanFactory) {
String[] parentResult = beanNamesForTypeIncludingAncestors(
(ListableBeanFactory) hbf.getParentBeanFactory(), type, includeNonSingletons, allowEagerInit);
List<String> resultList = new ArrayList<String>();
resultList.addAll(Arrays.asList(result));
for (String beanName : parentResult) {
//排除掉已经添加的beanName
if (!resultList.contains(beanName) && !hbf.containsLocalBean(beanName)) {
resultList.add(beanName);
}
}
result = StringUtils.toStringArray(resultList);
}
}
return result;
}
可以看到,获取beanName集合的功能是在ListableBeanFactory定义的,上面代码除了调用该方法,还会对父BeanFactory进行递归的搜索(HierarchicalBeanFactory提供父BeanFactory功能的支持)。
DefaultListableBeanFactory即继承了ListableBeanFactory,又继承了HierarchicalBeanFactory。
下面是DefaultListableBeanFactory对ListableBeanFactory功能的实现:
public String[] getBeanNamesForType(Class<?> type, boolean includeNonSingletons, boolean allowEagerInit) {
//如果type为null,ResolvableType.forRawClass(type)会返回Object.class
if (!isConfigurationFrozen() || type == null || !allowEagerInit) {
return doGetBeanNamesForType(ResolvableType.forRawClass(type), includeNonSingletons, allowEagerInit);
}
//先尝试从缓存中获取
Map<Class<?>, String[]> cache =
(includeNonSingletons ? this.allBeanNamesByType : this.singletonBeanNamesByType);
String[] resolvedBeanNames = cache.get(type);
if (resolvedBeanNames != null) {
return resolvedBeanNames;
}
//获取结果后再放入缓存(如果安全的话,对ClassLoader的验证,避免Class是由不同ClassLoader加载的,而造成类型不匹配的问题)
resolvedBeanNames = doGetBeanNamesForType(ResolvableType.forRawClass(type), includeNonSingletons, true);
if (ClassUtils.isCacheSafe(type, getBeanClassLoader())) {
cache.put(type, resolvedBeanNames);
}
return resolvedBeanNames;
}
2.doGetBeanNamesForType
上面代码是对获取的BeanName提供了缓存的功能,具体的搜索操作交给了doGetBeanNamesForType完成:
private String[] doGetBeanNamesForType(ResolvableType type, boolean includeNonSingletons, boolean allowEagerInit) {
List<String> result = new ArrayList<String>();
//Spring会遍历所有beanDefinitionNames
for (String beanName : this.beanDefinitionNames) {
// 筛选掉bean的别名,只会对bean的id进行操作
if (!isAlias(beanName)) {
try {
RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
// 验证BeanDefinition的完整性
if (!mbd.isAbstract() && (allowEagerInit ||
((mbd.hasBeanClass() || !mbd.isLazyInit() || isAllowEagerClassLoading())) &&
!requiresEagerInitForType(mbd.getFactoryBeanName()))) {
// 是否是FactoryBean
boolean isFactoryBean = isFactoryBean(beanName, mbd);
//获取BeanDefinition装饰的BeanDefinition,如果有的话
BeanDefinitionHolder dbd = mbd.getDecoratedDefinition();
//非工厂bean的判断
boolean matchFound =
(allowEagerInit || !isFactoryBean ||
(dbd != null && !mbd.isLazyInit()) || containsSingleton(beanName)) &&
(includeNonSingletons ||
(dbd != null ? mbd.isSingleton() : isSingleton(beanName))) &&
isTypeMatch(beanName, type);
if (!matchFound && isFactoryBean) {
// 工厂bean的判断
beanName = FACTORY_BEAN_PREFIX + beanName;
matchFound = (includeNonSingletons || mbd.isSingleton()) && isTypeMatch(beanName, type);
}
if (matchFound) {
//如果条件符合,添加到结果集
result.add(beanName);
}
}
}
//catch 略
}
}
// 对手动添加的单例beanName进行搜索
for (String beanName : this.manualSingletonNames) {
try {
// 与前面逻辑相同,分为工厂bean和普通bean两种情况进行判断
if (isFactoryBean(beanName)) {
if ((includeNonSingletons || isSingleton(beanName)) && isTypeMatch(beanName, type)) {
result.add(beanName);
continue;
}
beanName = FACTORY_BEAN_PREFIX + beanName;
}
if (isTypeMatch(beanName, type)) {
result.add(beanName);
}
}
//catch 略
}
return StringUtils.toStringArray(result);
}
为了实现获取特定类型的bean,Spring会遍历所有已保存的beanName(不包括别名),对每个beanName对应的bean定义进行判断,将符合的beanName添加到结果集中
最后
以上就是粗暴母鸡为你收集整理的Spring源码:bean创建(五)解决依赖一、resolveDependency二、搜索类型匹配的bean列表的全部内容,希望文章能够帮你解决Spring源码:bean创建(五)解决依赖一、resolveDependency二、搜索类型匹配的bean列表所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复