依赖注入底层原理流程图: https://www.processon.com/view/link/5f899fa5f346fb06e1d8f570
上一篇分析@Autowired是如何自动注入的,首先通过遍历构建成bean的类的字段和方法找到注入点,这个过程在BeanDefinition后置处理中完成,找到后保存起来。到了属性注入阶段把注入点拿出来,通过inject
方法赋值,inject
方法最终赋值是通过反射进行赋值。但是在inject
中如何找到属性对应的bean没有分析,下面接着来分析。
value = resolveFieldValue(field, bean, beanName);
和arguments = resolveMethodArguments(method, bean, beanName);
分别是找属性对应的bean和找方法参数对应的bean。
属性如何找bean
@Nullable
private Object resolveFieldValue(Field field, Object bean, @Nullable String beanName) {
//构建注入点的描述器
DependencyDescriptor desc = new DependencyDescriptor(field, this.required);
desc.setContainingClass(bean.getClass());
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) {
throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(field), ex);
}
synchronized (this) {
if (!this.cached) {
Object cachedFieldValue = null;
if (value != null || this.required) {
cachedFieldValue = desc;
// 注册一下beanName依赖了autowiredBeanNames
registerDependentBeans(beanName, autowiredBeanNames);
if (autowiredBeanNames.size() == 1) {
String autowiredBeanName = autowiredBeanNames.iterator().next();
if (beanFactory.containsBean(autowiredBeanName) &&
beanFactory.isTypeMatch(autowiredBeanName, field.getType())) {
// 构造一个ShortcutDependencyDescriptor作为缓存,保存了当前filed所匹配的autowiredBeanName,而不是对应的bean对象(考虑原型bean)
cachedFieldValue = new ShortcutDependencyDescriptor(
desc, autowiredBeanName, field.getType());
}
}
}
this.cachedFieldValue = cachedFieldValue;
this.cached = true;
}
}
return value;
}
}
首先通过属性构造一个注入点的描述器DependencyDescriptor,通过核心方法value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter)
获取到对应的bean进行返回。
DependencyDescriptor
DependencyDescriptor包含了方法、属性的元数据信息(方法类型,名称,属性类型,属性名称等)。
方法参数如何找Bean
@Nullable
private Object[] resolveMethodArguments(Method method, Object bean, @Nullable String beanName) {
//获取方法参数的个数
int argumentCount = method.getParameterCount();
//构造出参数的数组
Object[] arguments = new Object[argumentCount];
//DependencyDescriptor注入点描述器 就是把需要属性注入的方法、字段封装到一个类当中
DependencyDescriptor[] descriptors = new DependencyDescriptor[argumentCount];
Set<String> autowiredBeans = new LinkedHashSet<>(argumentCount);
Assert.state(beanFactory != null, "No BeanFactory available");
TypeConverter typeConverter = beanFactory.getTypeConverter();
// 遍历每个方法参数,找到匹配的bean对象
for (int i = 0; i < arguments.length; i++) {
//表示方法的第i个参数 就是封装了一下
MethodParameter methodParam = new MethodParameter(method, i);
// this.required 就是@autowire require的值
// 二次封装
DependencyDescriptor currDesc = new DependencyDescriptor(methodParam, this.required);
currDesc.setContainingClass(bean.getClass());
descriptors[i] = currDesc;
try {
//核心方法 找参数对应的bean
Object arg = beanFactory.resolveDependency(currDesc, beanName, autowiredBeans, typeConverter);
if (arg == null && !this.required) {
arguments = null;
break;
}
//把找到的bean放到数组当中
arguments[i] = arg;
}
catch (BeansException ex) {
throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(methodParam), ex);
}
}
synchronized (this) {
if (!this.cached) {
if (arguments != null) {
DependencyDescriptor[] cachedMethodArguments = Arrays.copyOf(descriptors, arguments.length);
registerDependentBeans(beanName, autowiredBeans);
if (autowiredBeans.size() == argumentCount) {
Iterator<String> it = autowiredBeans.iterator();
Class<?>[] paramTypes = method.getParameterTypes();
for (int i = 0; i < paramTypes.length; i++) {
String autowiredBeanName = it.next();
if (beanFactory.containsBean(autowiredBeanName) &&
beanFactory.isTypeMatch(autowiredBeanName, paramTypes[i])) {
cachedMethodArguments[i] = new ShortcutDependencyDescriptor(
descriptors[i], autowiredBeanName, paramTypes[i]);
}
}
}
this.cachedMethodArguments = cachedMethodArguments;
}
else {
this.cachedMethodArguments = null;
}
this.cached = true;
}
}
return arguments;
}
}
这个过程也差不多最终也是根据Object arg = beanFactory.resolveDependency(currDesc, beanName, autowiredBeans, typeConverter);
找到bean。不过是属性zhaobean还是方法参数找bean最终都是通过beanFactory.resolveDependency
方法找到bean。
beanFactory.resolveDependency(currDesc, beanName, autowiredBeans, typeConverter)
传入注入点描述器、beanName、集合、类型转换器。
public Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName,
@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
// 用来获取方法入参名字的
// getParameterNameDiscoverer() 采用反射 或者本地变量表
descriptor.initParameterNameDiscovery(getParameterNameDiscoverer());
// 所需要的类型是Optional
if (Optional.class == descriptor.getDependencyType()) {
return createOptionalDependency(descriptor, requestingBeanName);
}
// 所需要的的类型是ObjectFactory,或ObjectProvider
else if (ObjectFactory.class == descriptor.getDependencyType() ||
ObjectProvider.class == descriptor.getDependencyType()) {
return new DependencyObjectProvider(descriptor, requestingBeanName);
}
else if (javaxInjectProviderClass == descriptor.getDependencyType()) {
return new Jsr330Factory().createDependencyProvider(descriptor, requestingBeanName);
}
else {
//判断属性或者set方法上有没有@Lazy注解 如果有则构造一个代理对象并返回 真正使用该代理对象时才进行类型筛选Bean
// 如果没有返回null
Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(
descriptor, requestingBeanName);
if (result == null) {
// descriptor表示某个属性或某个set方法
// requestingBeanName表示正在进行依赖注入的Bean
//核心方法
result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
}
return result;
}
}
这个过程对注入点的类型进行判断做出对应处理,重点来看对@Lazy注解的处理,如果注入点标记有@Lazy那么注入的是代理对象,而不是真正的bean对象。如果没有@Lazy返回null,然后通过doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
找到bean赋值给result 然后方法返回result 。
public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName,
@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
InjectionPoint previousInjectionPoint = ConstructorResolver.setCurrentInjectionPoint(descriptor);
try {
// 如果当前descriptor之前做过依赖注入了,则可以直接取shortcut了,相当于缓存
Object shortcut = descriptor.resolveShortcut(this);
if (shortcut != null) {
return shortcut;
}
//获取类型 有可能是字段的类型 也可能是方法参数的类型
Class<?> type = descriptor.getDependencyType();
// 获取@Value所指定的值 例如@Value("aaa") 就是获取到aaa
Object value = getAutowireCandidateResolver().getSuggestedValue(descriptor);
//对@value注解的处理
if (value != null) {
//如果是String类型
if (value instanceof String) {
// 占位符填充(${})
String strVal = resolveEmbeddedValue((String) value);
BeanDefinition bd = (beanName != null && containsBean(beanName) ?
getMergedBeanDefinition(beanName) : null);
// 解析Spring表达式(#{})
value = evaluateBeanDefinitionString(strVal, bd);
}
// 将value转化为descriptor所对应的类型
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()));
}
}
// 如果descriptor所对应的类型是数组、Map这些,就把匹配的bean全都放入到数组、map等当中
Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);
if (multipleBeans != null) {
return multipleBeans;
}
// 找到所有符合类型的Bean记录到map当中
// 核心方法 findAutowireCandidates 如何根据类型找到对应bean的过程
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
if (matchingBeans.isEmpty()) {
// required为true,抛异常
if (isRequired(descriptor)) {
raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
}
return null;
}
String autowiredBeanName;
Object instanceCandidate;
//如果找到的bean大于一个 进一步的筛选 否则执行else的方法
if (matchingBeans.size() > 1) {
// 根据类型找到了多个Bean,进一步筛选出某一个bean
//返回beanName 后续从map中将具体的bean找出来
// 大致过程: 先判断有bean有没有@Primary 在判断优先级 最后根据名称找bean
autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor);
//这个if表示 如果通过上面的方法 找不到合适bean 再判断isRequired属性 如果为true 则抛出异常
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;
}
}
//根据beanName获取具体的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();
}
// 记录匹配过的beanName
if (autowiredBeanNames != null) {
autowiredBeanNames.add(autowiredBeanName);
}
// 有可能筛选出来的是某个bean已经实例化了 也有可能是的bean的class类型,如果是class类型此处就进行实例化
if (instanceCandidate instanceof Class) {
//具体就是调用getBean方法
instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this);
}
Object result = instanceCandidate;
//当使用@bean 定义了一个bean 但是 return null 的时候 就属于NullBean 类型
//如果符合这个类型 会判断isRequired属性 如果为true 就会抛异常
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());
}
return result;
}
finally {
ConstructorResolver.setCurrentInjectionPoint(previousInjectionPoint);
}
}
这个方法中大致过程分为以下几步
findAutowireCandidates(beanName, type, descriptor)
方法找到所有符合类型的bean。这个后面分析String autowiredBeanName
和Object instanceCandidate;
中,如果找到的bean大于1个执行determineAutowireCandidate(matchingBeans, descriptor)
determineAutowireCandidate(matchingBeans, descriptor)
方法就是筛选bean。首先判断bean有没有@Primary注解,有就返回。如果没有,判断@Priority 取优先级最高的bean。注意这里的优先级是@Priority不是@Order。如果还是没有,接着通过beanName进行和属性的名称进行匹配,找到符合的bean返回。返回同样记录autowiredBeanName
和instanceCandidate
。接下来主要分析findAutowireCandidates(beanName, type, descriptor)
这个方法如何找到bean。
findAutowireCandidates
protected Map<String, Object> findAutowireCandidates(
@Nullable String beanName, Class<?> requiredType, DependencyDescriptor descriptor) {
// 从BeanFactory中找出和requiredType所匹配的beanName,
// 仅仅是beanName,这些bean不一定经过了实例化,只有到最终确定某个Bean了,如果这个Bean还没有实例化才会真正进行实例化
//beanNamesForTypeIncludingAncestors 大致过程:在本容器和父容器中找bean
// 怎么找: 通过遍历所有beanName 获取对应RootBeanDefinition 根据RootBeanDefinition 做一系列判断
String[] candidateNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
this, requiredType, true, descriptor.isEager());
Map<String, Object> result = CollectionUtils.newLinkedHashMap(candidateNames.length);
// 根据类型从resolvableDependencies中匹配Bean
// resolvableDependencies中存放的是类型:Bean对象,比如BeanFactory.class:BeanFactory对象,在Spring启动时设置
for (Map.Entry<Class<?>, Object> classObjectEntry : this.resolvableDependencies.entrySet()) {
Class<?> autowiringType = classObjectEntry.getKey();
if (autowiringType.isAssignableFrom(requiredType)) {
Object autowiringValue = classObjectEntry.getValue();
autowiringValue = AutowireUtils.resolveAutowiringValue(autowiringValue, requiredType);
if (requiredType.isInstance(autowiringValue)) {
//把匹配的bean类型加入到result中 这个result就是上面找到符合的beanName的map
result.put(ObjectUtils.identityToString(autowiringValue), autowiringValue);
break;
}
}
}
//遍历所有匹配的beanName 然后根据条件把符合的beanName 加入到result当中
for (String candidate : candidateNames) {
// 如果不是自己,则判断该candidate到底能不能用来进行自动注入
//!isSelfReference(beanName, candidate) :判断是不是自己注入自己 如果不是接着判断
// isAutowireCandidate(candidate, descriptor) :判断这个bean能不能依赖注入 这里涉及到责任链模式
if (!isSelfReference(beanName, candidate) && isAutowireCandidate(candidate, descriptor)) {
addCandidateEntry(result, candidate, descriptor, requiredType);
}
}
// 为空要么是真的没有匹配的,要么是匹配的自己
if (result.isEmpty()) {
// 需要匹配的类型是不是Map、数组之类的
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);
}
}
// 匹配的是自己,被自己添加到result中
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;
}
大致过程:
找出BeanFactory中类型为type的所有的Bean的名字,注意是名字,而不是Bean对象,因为我们可以根据BeanDefinition就能判断和当前type是不是匹配,不用生成Bean对象
根据类型找beanName的底层流程:https://www.processon.com/view/link/6135bb430e3e7412ecd5d1f2
把resolvableDependencies中key为type的对象找出来并添加到result中
遍历根据type找出的beanName,判断当前beanName对应的Bean是不是能够被自动注入
先判断beanName对应的BeanDefinition中的autowireCandidate属性,如果为false,表示不能用来进行自动注入,如果为true则继续进行判断
判断当前type是不是泛型,如果是泛型是会把容器中所有的beanName找出来的,如果是这种情况,那么在这一步中就要获取到泛型的真正类型,然后进行匹配,如果当前beanName和当前泛型对应的真实类型匹配,那么则继续判断
如果当前DependencyDescriptor上存在@Qualifier注解,那么则要判断当前beanName上是否定义了Qualifier,并且是否和当前DependencyDescriptor上的Qualifier相等,相等则匹配
经过上述验证之后,当前beanName才能成为一个可注入的,添加到result中
整个依赖注入的执行流程:https://www.processon.com/view/link/5f8fdfa8e401fd06fd984f20
上面有个重要的点是isAutowireCandidate
方法。它是接口AutowireCandidateResolver
的默认方法,是用来判断@bean属性autowireCandidate
但是isAutowireCandidate
执行的其实是它的子类,是一个责任链模式
@Override
public boolean isAutowireCandidate(String beanName, DependencyDescriptor descriptor)
throws NoSuchBeanDefinitionException {
//该方法的顶级接口AutowireCandidateResolver 对isAutowireCandidate有默认方法 用来判断@bean属性autowireCandidate
//大致过程 :这里一个责任链模式
// SimpleAutowireCandidateResolver 从BeanDefinition层面判断BeanDefinition的属性isAutowireCandidate 符不符合依赖注入
// GenericTypeAwareAutowireCandidateResolver 从泛型层面 判断 符不符合依赖注入
// QualifierAnnotationAutowireCandidateResolver 判断@Qualifier注解的值 根据这个值去找对饮的bean
//调用过程就是 一开始会调用 QualifierAnnotationAutowireCandidateResolver
// 然后QualifierAnnotationAutowireCandidateResolver 调用父类 GenericTypeAwareAutowireCandidateResolver
// 然后GenericTypeAwareAutowireCandidateResolver 继续调用父类 SimpleAutowireCandidateResolver
return isAutowireCandidate(beanName, descriptor, getAutowireCandidateResolver());
}
getAutowireCandidateResolver() 得到的是ContextAnnotationAutowireCandidateResolver
所以会先调QualifierAnnotationAutowireCandidateResolver的isAutowireCandidate方法。
GenericTypeAwareAutowireCandidateResolver 用来判断泛型
QualifierAnnotationAutowireCandidateResolver 用来判断 @Qualifier
到此@Autowired自动注入分析到此结束,下篇分析@Resource和进行依赖注入的总结