概述
4.2 真正开始解析依赖项(最核心方法)
org.springframework.beans.factory.support.DefaultListableBeanFactory#doResolveDependency
public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName,
@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
//线程上设置当前注入点
InjectionPoint previousInjectionPoint = ConstructorResolver.setCurrentInjectionPoint(descriptor);
try {
//a.依赖注入的缓存,有缓存直接返回
// 如果descriptor是ShortcutDependencyDescriptor,相当于之前做过依赖注入且已经缓存了
// 那么直接根据缓存的BeanName,去容器里直接拿Bean
Object shortcut = descriptor.resolveShortcut(this);
if (shortcut != null) {
return shortcut;
}
//获取依赖注入的参数类型
Class<?> type = descriptor.getDependencyType();
//b.获取@Value所指定的值
Object value = getAutowireCandidateResolver().getSuggestedValue(descriptor);
if (value != null) {
//如果拿到是String:
if (value instanceof String) {
//c.解析嵌入值,占位符填充(${})
String strVal = resolveEmbeddedValue((String) value);
BeanDefinition bd = (beanName != null && containsBean(beanName) ?
getMergedBeanDefinition(beanName) : null);
//d.解析Spring表达式(#{})
//(根据Spring表达式得到的对象有可能直接就是一个Bean对象,也有可能是其他)
value = evaluateBeanDefinitionString(strVal, bd);
}
//e.将value转换为descriptor所对应的类型
TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
try {
return converter.convertIfNecessary(value, type, descriptor.getTypeDescriptor());
}
catch (UnsupportedOperationException ex) {...}
}
//f.注入多实例情况
//如果descriptor对应的类型是数组、Map、集合这些,就拿descriptor对应的类型去匹配所有的bean对象,不用进一步做筛选了
Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);
if (multipleBeans != null) {
return multipleBeans;
}
//g.根据类型查找所有候选Bean
// 找到所有Bean,key是BeanName,value有可能是Bean对象,有可能是BeanClass
// 依赖注入过程中,没必要把所有候选Bean都实例化
// 因为后续流程最多只会注入一个,保证注入的那个实例化过就OK了
// 而且后续判断是否匹配,有Class就够了
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
if (matchingBeans.isEmpty()) {
//required为true,且matchingBeans为空,则抛异常
if (isRequired(descriptor)) {
raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
}
//如果required不为true,则注入一个空属性
return null;
}
String autowiredBeanName;
Object instanceCandidate;
if (matchingBeans.size() > 1) {
//h.如果根据类型匹配到了多个Bean
//根据类型找到了多个Bean,进一步筛选出某一个 @Primary --> 优先级最高 --> name
autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor);
if (autowiredBeanName == null) {
//如果筛选不出来
if (isRequired(descriptor) || !indicatesMultipleBeans(type)) {
//如果required为true 或 type不是数组、集合、map
//indicatesMultipleBeans:判断type是否是 数组、集合、map
//这里直接抛异常
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).
// 在可选的Collection/Map的情况下,无声地忽略一个非唯一的情况:
// 它可能是多个常规bean的空集合(特别是在4.3之前,当我们甚至没有查找集合bean时)。
return null;
}
}
//筛选出一个
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();
}
//i.记录匹配过的BeanName
if (autowiredBeanNames != null) {
autowiredBeanNames.add(autowiredBeanName);
}
//j.有可能筛选出来的是某个bean的类型,此处就进行实例化,调用getBean
if (instanceCandidate instanceof Class) {
instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this);
}
Object result = instanceCandidate;
//k:NullBean
if (result instanceof NullBean) {
if (isRequired(descriptor)) {
//解析出来是NullBean,且required=true,则抛异常
raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
}
result = null;
}
//判断找到的Bean对象类型是否是期望注入的类型
if (!ClassUtils.isAssignableValue(type, result)) {
throw new BeanNotOfRequiredTypeException(autowiredBeanName, type, instanceCandidate.getClass());
}
//最终返回
return result;
}
finally {
ConstructorResolver.setCurrentInjectionPoint(previousInjectionPoint);
}
}
a. 依赖注入的缓存
缓存是什么时候放的呢?
以字段注入为例,回到上一节入口分析字段注入的时候:
private Object resolveFieldValue(Field field, Object bean, @Nullable String beanName) {
//构造依赖描述符对象
DependencyDescriptor desc = new DependencyDescriptor(field, this.required);
desc.setContainingClass(bean.getClass());
//autowiredBeanNames记录了需要注入的Bean的BeanName
Set<String> autowiredBeanNames = new LinkedHashSet<>(1);
Assert.state(beanFactory != null, "No BeanFactory available");
//类型转换器
TypeConverter typeConverter = beanFactory.getTypeConverter();
Object value;
try {
//核心方法,从工厂中解析依赖项要注入的值
value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);
}
catch (BeansException ex) {...}
synchronized (this) {
//拿到结果以后,判断是否缓存过了,没有就进行缓存
if (!this.cached) {
Object cachedFieldValue = null;
if (value != null || this.required) {
cachedFieldValue = desc;
//注册一下beanName依赖了autowiredBeanNames
registerDependentBeans(beanName, autowiredBeanNames);
//只有当前注入只会注入一个Bean的情况下才会缓存
// 比如如果字段类型是List<Xxx>,那autowiredBeanNames有可能是多个
if (autowiredBeanNames.size() == 1) {
String autowiredBeanName = autowiredBeanNames.iterator().next();
//工厂中包含这个Bean实例,且类型匹配是OK的,则进行缓存
if (beanFactory.containsBean(autowiredBeanName) &&
beanFactory.isTypeMatch(autowiredBeanName, field.getType())) {
//构造一个ShortcutDependencyDescriptor作为缓存,保存了当前field所匹配的autowiredBeanName
cachedFieldValue = new ShortcutDependencyDescriptor(
desc, autowiredBeanName, field.getType());
}
}
}
//标记/保存缓存
this.cachedFieldValue = cachedFieldValue;
this.cached = true;
}
}
return value;
}
看到缓存的对象类型就是ShortcutDependencyDescriptor,并且缓存的是BeanName!不是实例。
beanName是存在名为shortcut的成员变量:
缓存是什么时候用的呢?
比如原型Bean的情况,当第二次获取原型Bean,第二次注入的时候,会再次调用注入方法,还是以字段注入为例:
org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.AutowiredFieldElement#inject
protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
Field field = (Field) this.member;
Object value;
if (this.cached) {
//对于原型Bean,第一次创建的时候,也找注入点,然后进行注入,此时cached为false,注入完了之后cached为true
//第二次创建的时候,先找注入点(此时会拿到缓存好的注入点),也就是AutowiredFieldElement对象,此时cache为ture
//则会使用缓存cachedFieldValue,是一个ShortcutDependencyDescriptor对象
//注入点并没有缓存被注入的具体Bean对象,而是BeanName,这样就能保证注入到不同的原型Bean对象
try {
value = resolvedCachedArgument(beanName, this.cachedFieldValue);
}
catch (NoSuchBeanDefinitionException ex) {...}
}
else {...}
if (value != null) {
//反射给field赋值
ReflectionUtils.makeAccessible(field);
field.set(bean, value);
}
}
org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor#resolvedCachedArgument
private Object resolvedCachedArgument(@Nullable String beanName, @Nullable Object cachedArgument) {
//cachedArgument此时就是ShortcutDependencyDescriptor,它是DependencyDescriptor子类
if (cachedArgument instanceof DependencyDescriptor) {
DependencyDescriptor descriptor = (DependencyDescriptor) cachedArgument;
Assert.state(this.beanFactory != null, "No BeanFactory available");
//将缓存好的DependencyDescriptor对象作为入参,继续调用resolveDependency
return this.beanFactory.resolveDependency(descriptor, beanName, null, null);
}
else {
return cachedArgument;
}
}
继续调用beanFactory.resolveDependency,还是回到4.2 doResolveDependency方法:
默认实现DependencyDescriptor是返回null,但如果是缓存ShortcutDependencyDescriptor的实现:
shortcut存的就是BeanName,根据BeanName去容器里获取实例对象
为什么要这么做?这样就能保证注入到不同的原型Bean对象
b. 获取@Value所指定的值
@Value可以放在字段或方法入参上
@Value注释:
- 在字段或方法/构造函数参数级别使用的注解,指示被注解元素的默认值表达式。
- 通常用于表达式驱动或属性驱动的依赖注入。也支持处理程序方法参数的动态解析——例如,在Spring MVC中。
- 一个常见的用例是使用#{systemProperties.myProp}风格的SpEL (Spring Expression Language)表达式注入值。或者,可以使用${my.app.myProp}风格的属性占位符注入值。
默认实现走
org.springframework.beans.factory.annotation.QualifierAnnotationAutowireCandidateResolver#getSuggestedValue
public Object getSuggestedValue(DependencyDescriptor descriptor) {
//获取@Value注解上的value属性
//1.从参数级别获取(针对被包装的字段或方法/构造函数参数关联的注解)
Object value = findValue(descriptor.getAnnotations());
if (value == null) {
//2.方法级别上获取
//获取方法/构造函数上@Value注解的value属性(方法/构造函数级别,而不是参数级别)
MethodParameter methodParam = descriptor.getMethodParameter();
if (methodParam != null) {
//methodParam.getMethodAnnotations():
// 该方法公开在方法/构造函数本身上声明的注解(即在方法/构造函数级别,而不是在参数级别)
value = findValue(methodParam.getMethodAnnotations());
}
}
return value;
}
参数或方法上获取到注解以后都会调findValue方法,获取@Value注解的value属性:
org.springframework.beans.factory.annotation.QualifierAnnotationAutowireCandidateResolver#findValue
protected Object findValue(Annotation[] annotationsToSearch) {
if (annotationsToSearch.length > 0) { // qualifier annotations have to be local
//AnnotatedElementUtils是一个注解工具类
//获取合并后的注解属性(包括父注解)
//this.valueAnnotationType就是Value.class
AnnotationAttributes attr = AnnotatedElementUtils.getMergedAnnotationAttributes(
AnnotatedElementUtils.forAnnotations(annotationsToSearch), this.valueAnnotationType);
if (attr != null) {
return extractValue(attr);
}
}
return null;
}
protected Object extractValue(AnnotationAttributes attr) {
//AnnotationUtils.VALUE = "value"
Object value = attr.get(AnnotationUtils.VALUE);
if (value == null) {
throw new IllegalStateException("Value annotation must have a value attribute");
}
return value;
}
org.springframework.core.annotation.AnnotatedElementUtils#getMergedAnnotationAttributes(java.lang.reflect.AnnotatedElement, java.lang.Class<? extends java.lang.annotation.Annotation>)涉及到一个注解派生的概念,可以参考:
spring core:@Component的派生性
c. 占位符填充(${})
如果@Value拿到的是String,则会先解析嵌入值,进行占位符填充
底层就是拿testValue这个key,从Environment对象里找value(默认),找到就会替换,找不到就保持原样
而Environment包含了操作系统层的属性值、jvm层的属性值、properties文件(需要注册)中的属性值
jvm层的属性值-Dxxxx 的优先级比 properties文件配置的属性值 优先级高
org.springframework.beans.factory.support.AbstractBeanFactory#resolveEmbeddedValue
public String resolveEmbeddedValue(@Nullable String value) {
if (value == null) {
return null;
}
String result = value;
for (StringValueResolver resolver : this.embeddedValueResolvers) {
//解析器解析
result = resolver.resolveStringValue(result);
if (result == null) {
return null;
}
}
return result;
}
解析细节就不深究了,看下StringValueResolver初始化入口,应该是这个(和工厂生命周期有关,以后讲):
org.springframework.context.support.PropertySourcesPlaceholderConfigurer#postProcessBeanFactory,是一个BeanFactoryPostProcessor。
通过根据配置器的PropertySources集合解析每个占位符,替换bean定义中的${…}占位符来进行处理,其中包括:
- 所有环境属性源(如果存在一个环境)
- 合并的本地属性(如果已指定)
- 通过调用setPropertySources设置的任何属性源
如果调用setPropertySources,将忽略环境和本地属性。此方法旨在为用户提供对属性源的细粒度控制,一旦设置,配置器就不会对添加其他源进行任何假设。
d. 解析Spring表达式(#{})
Spring表达式(Spring EL)
org.springframework.beans.factory.support.AbstractBeanFactory#evaluateBeanDefinitionString
protected Object evaluateBeanDefinitionString(@Nullable String value, @Nullable BeanDefinition beanDefinition) {
if (this.beanExpressionResolver == null) {
return value;
}
Scope scope = null;
if (beanDefinition != null) {
String scopeName = beanDefinition.getScope();
if (scopeName != null) {
scope = getRegisteredScope(scopeName);
}
}
//SpringEl表达式原理也很复杂...
//解析Spring表达式(#{}),根据Spring表达式得到的对象有可能直接就是一个Bean对象,也有可能是其他
return this.beanExpressionResolver.evaluate(value, new BeanExpressionContext(this, scope));
}
e. 将value转换为descriptor所对应的类型
比如:
@Value配置的就是一个普通字符串,但是注入需要的类型是OrderService
这时就会尝试用类型转换器进行转换(类型转换器用法第一节说过)
f. 注入多实例情况
如果descriptor对应的类型是数组、Map、集合…这些,就拿descriptor对应的类型去匹配所有的bean对象,不用进一步做筛选了
比如:
org.springframework.beans.factory.support.DefaultListableBeanFactory#resolveMultipleBeans
private Object resolveMultipleBeans(DependencyDescriptor descriptor, @Nullable String beanName,
@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) {
Class<?> type = descriptor.getDependencyType();
//用于访问多个元素的流的依赖描述符标记。
if (descriptor instanceof StreamDependencyDescriptor) {...}
//数组情况
else if (type.isArray()) {...}
//集合情况
else if (Collection.class.isAssignableFrom(type) && type.isInterface()) {
//获取集合的泛型类型
Class<?> elementType = descriptor.getResolvableType().asCollection().resolveGeneric();
if (elementType == null) {
return null;
}
//g. 核心方法,根据类型查找所有候选Bean
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, elementType,
new MultiElementDescriptor(descriptor));
if (matchingBeans.isEmpty()) {
return null;
}
//i. 记录匹配过的BeanName
if (autowiredBeanNames != null) {
autowiredBeanNames.addAll(matchingBeans.keySet());
}
TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
//类型转换
Object result = converter.convertIfNecessary(matchingBeans.values(), type);
if (result instanceof List) {
//如果是list做一下排序
if (((List<?>) result).size() > 1) {
//可以指定比较器,默认是OrderComparator
Comparator<Object> comparator = adaptDependencyComparator(matchingBeans);
if (comparator != null) {
((List<?>) result).sort(comparator);
}
}
}
return result;
}
//Map情况
else if (Map.class == type) {
ResolvableType mapType = descriptor.getResolvableType().asMap();
Class<?> keyType = mapType.resolveGeneric(0);
//如果Map的key不是String,则不支持
if (String.class != keyType) {
return null;
}
//Map value的类型
Class<?> valueType = mapType.resolveGeneric(1);
if (valueType == null) {
return null;
}
//g.核心方法,根据类型查找所有候选Bean
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, valueType,
new MultiElementDescriptor(descriptor));
if (matchingBeans.isEmpty()) {
return null;
}
//i. 记录匹配过的BeanName
if (autowiredBeanNames != null) {
autowiredBeanNames.addAll(matchingBeans.keySet());
}
return matchingBeans;
}
else {
return null;
}
}
其实无论哪种情况,都会调用findAutowireCandidates方法,根据类型查找所有候选Bean,这是一个核心方法。
g. 根据类型查找所有候选Bean
org.springframework.beans.factory.support.DefaultListableBeanFactory#findAutowireCandidates
核心方法,见下一节。
h. 如果根据类型匹配到了多个Bean
org.springframework.beans.factory.support.DefaultListableBeanFactory#determineAutowireCandidate
protected String determineAutowireCandidate(Map<String, Object> candidates, DependencyDescriptor descriptor) {
Class<?> requiredType = descriptor.getDependencyType();
//candidates表示根据类型所找到的多个Bean,value有可能是class,有可能是Bean实例
//i. 判断这些Bean中是否有一个是@Primary的
String primaryCandidate = determinePrimaryCandidate(candidates, requiredType);
if (primaryCandidate != null) {
return primaryCandidate;
}
//ii. 根据@Priority取优先级最高的Bean
String priorityCandidate = determineHighestPriorityCandidate(candidates, requiredType);
if (priorityCandidate != null) {
return priorityCandidate;
}
// iii. Fallback
// 匹配依赖项的名字,要么是字段的名字,要么是set方法入参的名字
for (Map.Entry<String, Object> entry : candidates.entrySet()) {
String candidateName = entry.getKey();
Object beanInstance = entry.getValue();
//resolvableDependencies记录了某个类型对应某个Bean,启动Spring时会进行设置,比如BeanFactory.class对应beanFactory实例
//注意:如果是Spring自己的byType,descriptor.getDependencyName()将返回空,只有是@Autowired才会返回方法属性名或方法参数名
if ((beanInstance != null && this.resolvableDependencies.containsValue(beanInstance)) ||
matchesBeanName(candidateName, descriptor.getDependencyName())) {
return candidateName;
}
}
return null;
}
i. 判断这些Bean中是否有@Primary标记的
org.springframework.beans.factory.support.DefaultListableBeanFactory#determinePrimaryCandidate
protected String determinePrimaryCandidate(Map<String, Object> candidates, Class<?> requiredType) {
String primaryBeanName = null;
//遍历所有候选bean
for (Map.Entry<String, Object> entry : candidates.entrySet()) {
String candidateBeanName = entry.getKey();
Object beanInstance = entry.getValue();
//判断是否有@Primary标记
if (isPrimary(candidateBeanName, beanInstance)) {
if (primaryBeanName != null) {
//发现primaryBean存在多个,进一步判断
//新发现的这个是不是在当前工厂中定义的
boolean candidateLocal = containsBeanDefinition(candidateBeanName);
//上一个发现的是不是在当前工厂中定义的
boolean primaryLocal = containsBeanDefinition(primaryBeanName);
//如果存在多个@Primary Bean在当前工厂中,则会抛异常
if (candidateLocal && primaryLocal) {
throw new NoUniqueBeanDefinitionException(requiredType, candidates.size(),
"more than one 'primary' bean found among candidates: " + candidates.keySet());
}
//有可能之前找到的@Primary是在父工厂,肯定优先取当前工厂中的Bean
else if (candidateLocal) {
primaryBeanName = candidateBeanName;
}
}
else {
primaryBeanName = candidateBeanName;
}
}
}
return primaryBeanName;
}
判断是否有@Primary标记:
protected boolean isPrimary(String beanName, Object beanInstance) {
//获取规范BeanName
String transformedBeanName = transformedBeanName(beanName);
if (containsBeanDefinition(transformedBeanName)) {
//根据BeanDefinition判断是否是Primary
return getMergedLocalBeanDefinition(transformedBeanName).isPrimary();
}
//当前工厂不存在这个BeanDefinition,则判断父工厂
BeanFactory parent = getParentBeanFactory();
return (parent instanceof DefaultListableBeanFactory &&
((DefaultListableBeanFactory) parent).isPrimary(transformedBeanName, beanInstance));
}
ii. 根据@Priority取优先级最高的Bean
org.springframework.beans.factory.support.DefaultListableBeanFactory#determineHighestPriorityCandidate
protected String determineHighestPriorityCandidate(Map<String, Object> candidates, Class<?> requiredType) {
String highestPriorityBeanName = null;
Integer highestPriority = null;
//遍历所有候选Bean
for (Map.Entry<String, Object> entry : candidates.entrySet()) {
String candidateBeanName = entry.getKey();
Object beanInstance = entry.getValue();
if (beanInstance != null) {
//获取当前Bean的优先级,解析的是@Priority注解
Integer candidatePriority = getPriority(beanInstance);
if (candidatePriority != null) {
if (highestPriorityBeanName != null) {
//与之前优先级最高的进行比较
//优先级相同则抛异常
if (candidatePriority.equals(highestPriority)) {
throw new NoUniqueBeanDefinitionException(requiredType, candidates.size(),
"Multiple beans found with the same priority ('" + highestPriority +
"') among candidates: " + candidates.keySet());
}
//比较优先级,数字越小优先级越高
else if (candidatePriority < highestPriority) {
//记录新的最高优先级
highestPriorityBeanName = candidateBeanName;
highestPriority = candidatePriority;
}
}
else {
//第一次记录最高优先级
highestPriorityBeanName = candidateBeanName;
highestPriority = candidatePriority;
}
}
}
}
return highestPriorityBeanName;
}
解析@Priority注解:
protected Integer getPriority(Object beanInstance) {
//依赖注入用的排序比较器
Comparator<Object> comparator = getDependencyComparator();
if (comparator instanceof OrderComparator) {
//获取优先级
return ((OrderComparator) comparator).getPriority(beanInstance);
}
return null;
}
OrderComparator默认实现是AnnotationAwareOrderComparator
org.springframework.core.annotation.AnnotationAwareOrderComparator#getPriority
public Integer getPriority(Object obj) {
if (obj instanceof Class) {
//从类上获取@Priority的value值
return OrderUtils.getPriority((Class<?>) obj);
}
//obj也有可能是实例
Integer priority = OrderUtils.getPriority(obj.getClass());
if (priority == null && obj instanceof DecoratingProxy) {
//如果obj是装饰类代理,则返回这个代理后面的(最终)装饰类
//根据装饰类(代理背后真正的类)获取优先级
return getPriority(((DecoratingProxy) obj).getDecoratedClass());
}
return priority;
}
org.springframework.core.annotation.OrderUtils#getPriority
public static Integer getPriority(Class<?> type) {
//SearchStrategy.TYPE_HIERARCHY:执行整个类型层次结构的完整搜索,包括超类和实现的接口。
//JAVAX_PRIORITY_ANNOTATION="javax.annotation.Priority"
//MergedAnnotation.VALUE="value"
return MergedAnnotations.from(type, SearchStrategy.TYPE_HIERARCHY).get(JAVAX_PRIORITY_ANNOTATION)
.getValue(MergedAnnotation.VALUE, Integer.class).orElse(null);
}
iii. 匹配依赖项的名字
// Fallback
// 匹配依赖项的名字,要么是字段的名字,要么是set方法入参的名字
for (Map.Entry<String, Object> entry : candidates.entrySet()) {
String candidateName = entry.getKey();
Object beanInstance = entry.getValue();
//resolvableDependencies记录了某个类型对应某个Bean实例(启动Spring时会进行设置,比如BeanFactory.class对应beanFactory实例)
//注意:如果是Spring自己的byType,descriptor.getDependencyName()将返回空,只有是@Autowired才会返回字段属性名或方法参数名
if ((beanInstance != null && this.resolvableDependencies.containsValue(beanInstance)) ||
matchesBeanName(candidateName, descriptor.getDependencyName())) {
return candidateName;
}
}
resolvableDependencies:类似于一个缓存,事先指定了类和实例的映射关系,只要是注入这个类型,就用这个类型对应的实例进行注入
获取依赖项名字:
org.springframework.beans.factory.config.DependencyDescriptor#getDependencyName
public String getDependencyName() {
//字段类型,直接field.getName
return (this.field != null ? this.field.getName() : obtainMethodParameter().getParameterName());
}
//org.springframework.core.MethodParameter#getParameterName
public String getParameterName() {
if (this.parameterIndex < 0) {
return null;
}
//方法参数类型,则用参数名字发现器
ParameterNameDiscoverer discoverer = this.parameterNameDiscoverer;
if (discoverer != null) {
String[] parameterNames = null;
//解析方法的入参名
if (this.executable instanceof Method) {
parameterNames = discoverer.getParameterNames((Method) this.executable);
}
//解析构造函数的入参名
else if (this.executable instanceof Constructor) {
parameterNames = discoverer.getParameterNames((Constructor<?>) this.executable);
}
if (parameterNames != null) {
this.parameterName = parameterNames[this.parameterIndex];
}
this.parameterNameDiscoverer = null;
}
return this.parameterName;
}
候选BeanName 和 依赖项name匹配:
org.springframework.beans.factory.support.DefaultListableBeanFactory#matchesBeanName
protected boolean matchesBeanName(String beanName, @Nullable String candidateName) {
//getAliases(beanName):获取beanName所有的别名
return (candidateName != null &&
(candidateName.equals(beanName) || ObjectUtils.containsElement(getAliases(beanName), candidateName)));
}
i. 记录匹配过的BeanName
注意这个集合,以字段注入为例,方法注入同理:
在解析依赖项的时候,当找到需要注入的Bean后,会把Bean的名字放到这个集合里:
等全部找完以后,会记录当前Bean,依赖了这些Bean
以前讲DependsOn时说过,并且销毁Bean时也会用到。
j. 筛选出来的是Class
有可能筛选出来的是某个bean的类型,此处就进行实例化,调用getBean
因为依赖注入过程中,没必要把所有候选Bean都实例化
后续流程最多只会注入一个,保证注入的那个实例化过就OK了
而且后续判断是否匹配,有Class就够了
org.springframework.beans.factory.config.DependencyDescriptor#resolveCandidate
public Object resolveCandidate(String beanName, Class<?> requiredType, BeanFactory beanFactory)
throws BeansException {
return beanFactory.getBean(beanName);
}
k:NullBean
这样配置就是一个NullBean,不是null
最后
以上就是狂野小白菜为你收集整理的Spring源码分析(十)依赖注入源码解析3:DefaultListableBeanFactory#doResolveDependency 真正开始解析依赖项4.2 真正开始解析依赖项(最核心方法)a. 依赖注入的缓存b. 获取@Value所指定的值c. 占位符填充(${})d. 解析Spring表达式(#{})e. 将value转换为descriptor所对应的类型f. 注入多实例情况g. 根据类型查找所有候选Beanh. 如果根据类型匹配到了多个Beani. 记录匹配过的BeanNamej.的全部内容,希望文章能够帮你解决Spring源码分析(十)依赖注入源码解析3:DefaultListableBeanFactory#doResolveDependency 真正开始解析依赖项4.2 真正开始解析依赖项(最核心方法)a. 依赖注入的缓存b. 获取@Value所指定的值c. 占位符填充(${})d. 解析Spring表达式(#{})e. 将value转换为descriptor所对应的类型f. 注入多实例情况g. 根据类型查找所有候选Beanh. 如果根据类型匹配到了多个Beani. 记录匹配过的BeanNamej.所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复