版本: Spring-beans-5.2.5.RELEASE
假定環(huán)境中存在兩個User對象描睦,分別是user眨业、superUser薪缆,其中superUser標(biāo)注了primary屬性烛缔,根據(jù)這個前提條件怒竿,來看看Spring如何查找要依賴注入的對象
@Configuration
public class AnnotationDependencyInjectionResolutionDemo {
@Autowired // 依賴查找(處理) + 延遲
@Lazy
private User lazyUser;
@Autowired // 依賴查找(處理)
private User user;
@Autowired // 集合類型依賴注入
private Map<String, User> users; // user superUser
public static void main(String[] args) {
// 創(chuàng)建 BeanFactory 容器
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
// 注冊 Configuration Class(配置類) -> Spring Bean
applicationContext.register(AnnotationDependencyInjectionResolutionDemo.class);
XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(applicationContext);
String xmlResourcePath = "classpath:/META-INF/dependency-lookup-context.xml";
// 加載 XML 資源,解析并且生成 BeanDefinition
beanDefinitionReader.loadBeanDefinitions(xmlResourcePath);
// 啟動 Spring 應(yīng)用上下文
applicationContext.refresh();
// 顯示地關(guān)閉 Spring 應(yīng)用上下文
applicationContext.close();
}
}
Spring框架的依賴查找工作由DefaultListableBeanFactory
類負(fù)責(zé)稳其,它實現(xiàn)了AutowireCapableBeanFactory
接口驶赏,該接口中定義了如下解析依賴屬性的方法
public interface AutowireCapableBeanFactory extends BeanFactory {
// ...
/**
* Resolve the specified dependency against the beans defined in this factory.
* @param descriptor the descriptor for the dependency (field/method/constructor)
* @param requestingBeanName the name of the bean which declares the given dependency
*/
@Nullable
Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName)
throws BeansException;
/**
* Resolve the specified dependency against the beans defined in this factory.
* @param descriptor the descriptor for the dependency (field/method/constructor)
* @param requestingBeanName the name of the bean which declares the given dependency
*/
@Nullable
Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName,
@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter)
throws BeansException;
}
從上面的resolveDependency`接口定義中可以了解都需要一個
DependencyDescriptor``對象,這個類描述了一個依賴屬性的相關(guān)信息,如下:
public class DependencyDescriptor extends InjectionPoint implements Serializable {
// 屬性定義在哪個類中,本例中值為AnnotationDependencyInjectionResolutionDemo
private final Class<?> declaringClass;
@Nullable
private String methodName; // 通過方法注入可用的方法名稱
@Nullable
private Class<?>[] parameterTypes;
private int parameterIndex;
@Nullable
private String fieldName; // 屬性名稱
private final boolean required; // 對應(yīng)@Autowired注解的required屬性
private final boolean eager; // 對應(yīng)@Lazy注解担映,是否懶加載,懶加載此項為false
private int nestingLevel = 1; // 嵌套層數(shù)
@Nullable
private Class<?> containingClass; // 類似declaringClass屬性
@Nullable
private volatile ResolvableType resolvableType; // 屬性的類型描述
// ...
}
再來看看DefaultListableBeanFactory
的實現(xiàn)蚯姆,針對普通類型的Bean,Spring會判斷當(dāng)前依賴屬性是單一類型還是多類型洒敏,針對單一類型龄恋,如果查找到多個候選bean,則判斷是否有首選Bean可以返回凶伙,否則拋出異常郭毕,而針對多類型的屬性依賴,直接遍歷所有符合的Bean返回
public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory
implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable {
// ...
@Override
@Nullable
public Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName,
@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter)
throws BeansException {
descriptor.initParameterNameDiscovery(getParameterNameDiscoverer());
// 首先函荣,可以看到Spring先判斷依賴注入的屬性是否為
// Optional显押、ObjectFactory、javaxInjectProviderClass 類型之一
if (Optional.class == descriptor.getDependencyType()) {
return createOptionalDependency(descriptor, requestingBeanName);
} 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 {
// 由于本例沒有上面的任何注入類型傻挂,會走這個分支煮落,
// 同時,第一個LazyUser屬性由于標(biāo)注了@Lazy注解踊谋,那么會直接生成一個CGLIB代理對象返回
Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(
descriptor, requestingBeanName);
if (result == null) {
// user和users屬性則進(jìn)入當(dāng)前方法
result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
}
return result;
}
}
@Nullable
public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName,
@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter)
throws BeansException {
InjectionPoint previousInjectionPoint = ConstructorResolver.setCurrentInjectionPoint(descriptor);
try {
// 省略和本例無關(guān)代碼...
// users屬性將會通過這個方法直接返回查找到的對象
// 顧名思義,這是一個解析多個bean集合屬性的方法
Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);
if (multipleBeans != null) {
return multipleBeans;
}
// user屬性將會通過這個方法獲得兩個候選bean信息旋讹,即user殖蚕、superUser
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
if (matchingBeans.isEmpty()) {
if (isRequired(descriptor)) {
raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
}
return null;
}
String autowiredBeanName;
Object instanceCandidate;
if (matchingBeans.size() > 1) {
// 通過這個方法推斷如果有多個候選bean可以注入單一類型屬性,則嘗試推斷
// 是否有哪個屬性標(biāo)注了@Primary之類的主要bean信息沉迹,通過這里得到superUser
autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor);
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;
}
}
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();
}
if (autowiredBeanNames != null) {
autowiredBeanNames.add(autowiredBeanName);
}
if (instanceCandidate instanceof Class) {
// 最終通過這個方法從beanFactory中獲取目標(biāo)bean返回
instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this);
}
Object result = instanceCandidate;
// 省略...
return result;
} finally {
ConstructorResolver.setCurrentInjectionPoint(previousInjectionPoint);
}
}
// 處理多元素屬性的注入查找
@Nullable
private Object resolveMultipleBeans(DependencyDescriptor descriptor, @Nullable String beanName,
@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) {
final Class<?> type = descriptor.getDependencyType();
if (descriptor instanceof StreamDependencyDescriptor) {
// ...
} else if (type.isArray()) {
// ...
} else if (Collection.class.isAssignableFrom(type) && type.isInterface()) {
// ...
} else if (Map.class == type) {
ResolvableType mapType = descriptor.getResolvableType().asMap();
Class<?> keyType = mapType.resolveGeneric(0);
if (String.class != keyType) {
return null;
}
Class<?> valueType = mapType.resolveGeneric(1);
if (valueType == null) {
return null;
}
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, valueType,
new MultiElementDescriptor(descriptor));
if (matchingBeans.isEmpty()) {
return null;
}
if (autowiredBeanNames != null) {
autowiredBeanNames.addAll(matchingBeans.keySet());
}
return matchingBeans;
} else {
return null;
}
}
protected Map<String, Object> findAutowireCandidates(
@Nullable String beanName, Class<?> requiredType, DependencyDescriptor descriptor) {
String[] candidateNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
this, requiredType, true, descriptor.isEager());
Map<String, Object> result = new LinkedHashMap<>(candidateNames.length);
// ... 省略
// 注意本方法返回的是Map<String,Object>睦疫,
// 當(dāng)解析多元素注入屬性的時候,value為具體的bean鞭呕,通過這個方法獲取具體的bean
for (String candidate : candidateNames) {
if (!isSelfReference(beanName, candidate) && isAutowireCandidate(candidate, descriptor)) {
addCandidateEntry(result, candidate, descriptor, requiredType);
}
// ... 省略
}
private void addCandidateEntry(Map<String, Object> candidates, String candidateName,
DependencyDescriptor descriptor, Class<?> requiredType) {
if (descriptor instanceof MultiElementDescriptor) {
// 通過這個方法向beanFactory獲取目標(biāo)bean
Object beanInstance = descriptor.resolveCandidate(candidateName, requiredType, this);
if (!(beanInstance instanceof NullBean)) {
candidates.put(candidateName, beanInstance);
}
}
// ...
}
}
參考圖
依賴注入處理過程(查找bean蛤育,無注入).png