Spring原始碼解析——依賴注入(二)
前面說到Spring 通過bytype注入,留下了一些沒有訴說,現在來詳細看看
protected void autowireByType(
String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {
TypeConverter converter = getCustomTypeConverter();
if (converter == null) {
converter = bw;
}
Set<String> autowiredBeanNames = new LinkedHashSet<>(4);
// 找到有對應set方法的屬性
String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
for (String propertyName : propertyNames) {
try {
PropertyDescriptor pd = bw.getPropertyDescriptor(propertyName);
// Don't try autowiring by type for type Object: never makes sense,
// even if it technically is a unsatisfied, non-simple property.
//這裡是判斷是你的屬性描述器,也就是說你的set方法的引數的型別不能是Object
//因為如果setUserService(Object userService),那麼像這個方法,如果是Object,spring根本不知道你要注入那個bean
//所以不能是Object
if (Object.class != pd.getPropertyType()) {
// set方法中的引數資訊
//根據屬性描述器獲取這個set方法的引數資訊
MethodParameter methodParam = BeanUtils.getWriteMethodParameter(pd);
// Do not allow eager init for type matching in case of a prioritized post-processor.
boolean eager = !(bw.getWrappedInstance() instanceof PriorityOrdered);
/**
*
* 根據方法的引數MethodParameter獲取一個bean
* 到這裡知道這個方法是byType,byType的原理是根據你的set方法的引數型別得到一個bean,所以這裡是通過
* set方法的引數比如setUserService(UserService uservice)中的UserService來構建一個依賴描述器
* 這個依賴描述器得到過後,根據這個依賴描述器和其他一些引數得到一個bean
*/
DependencyDescriptor desc = new AutowireByTypeDependencyDescriptor(methodParam, eager);
// 根據型別找bean,這就是byType
//簡單來說就是根據依賴描述器通過下面這個方法得到一個Bean,然後注入到pvs中
//後面說
Object autowiredArgument = resolveDependency(desc, beanName, autowiredBeanNames, converter);
if (autowiredArgument != null) {
pvs.add(propertyName, autowiredArgument);
}
for (String autowiredBeanName : autowiredBeanNames) {
registerDependentBean(autowiredBeanName, beanName);
if (logger.isTraceEnabled()) {
logger.trace("Autowiring by type from bean name '" + beanName + "' via property '" +
propertyName + "' to bean named '" + autowiredBeanName + "'");
}
}
autowiredBeanNames.clear();
}
} catch (BeansException ex) {
throw new UnsatisfiedDependencyException(mbd.getResourceDescription(), beanName, propertyName, ex);
}
}
}
- 找到有對應set方法的屬性
String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
protected String[] unsatisfiedNonSimpleProperties(AbstractBeanDefinition mbd, BeanWrapper bw) {
Set<String> result = new TreeSet<>();
PropertyValues pvs = mbd.getPropertyValues(); // 在BeanDefinition中新增的屬性和值,
//
PropertyDescriptor[] pds = bw.getPropertyDescriptors();
// 對類裡所有的屬性進行過濾,確定哪些屬性是需要進行自動裝配的
for (PropertyDescriptor pd : pds) {
// 屬性有set方法,並且
// 沒有通過DependencyCheck排除,並且
// 沒有在BeanDefinition中給該屬性賦值,並且
// 屬性的型別不是簡單型別
if (pd.getWriteMethod() != null && !isExcludedFromDependencyCheck(pd) && !pvs.contains(pd.getName()) &&
!BeanUtils.isSimpleProperty(pd.getPropertyType())) {
result.add(pd.getName());
}
}
// 返回過濾之後的結果,後續只對這些屬性進行自動裝配
return StringUtils.toStringArray(result);
}
- 得到屬性描述
getPropertyDescriptor
,根據屬性描述器獲取這個set方法的引數資訊getWriteMethodParameter
,然後根據方法的引數MethodParameter構建一個依賴描述器通過AutowireByTypeDependencyDescriptor
- 根據依賴描述器得到一個Bean通過
resolveDependency
public Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName,
@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
// DependencyDescriptor表示一個依賴,可以是一個屬性欄位,可能是一個構造方法引數,可能是一個set方法引數
// 根據descriptor去BeanFactory中找到bean
descriptor.initParameterNameDiscovery(getParameterNameDiscoverer());
// 如果依賴的型別是Optional
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 {
Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(
descriptor, requestingBeanName);
if (result == null) {
// 通過解析descriptor找到bean物件
result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
}
return result;
}
}
- 判斷descriptor.getDependencyType()的型別
- 若果依賴描述上存在@Lazy註解,那麼會生成一個代理物件,然後返回包裝成Optional否則呼叫doResolveDependen
通過解析依賴描述找到bean物件result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter)
public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName,
@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
InjectionPoint previousInjectionPoint = ConstructorResolver.setCurrentInjectionPoint(descriptor);
try {
// 如果DependencyDescriptor是一個ShortcutDependencyDescriptor,
// 那麼會直接理解beanName從beanFactory中拿到一個bean,
// 在利用@Autowired註解來進行依賴注入時會利用ShortcutDependencyDescriptor來進行依賴注入的快取,
// 表示當解析完某個依賴資訊後,會把依賴的bean的beanName快取起來
Object shortcut = descriptor.resolveShortcut(this);
if (shortcut != null) {
return shortcut;
}
// 獲取descriptor具體的型別,某個Filed的型別或某個方法引數的型別
Class<?> type = descriptor.getDependencyType();
// 獲取@Value註解中所配置的值
Object value = getAutowireCandidateResolver().getSuggestedValue(descriptor); // 是否通過@Value註解指定了值
if (value != null) {
if (value instanceof String) {
// 先進行佔位符的填充,解析"$"符號
String strVal = resolveEmbeddedValue((String) value);
BeanDefinition bd = (beanName != null && containsBean(beanName) ?
getMergedBeanDefinition(beanName) : null);
// 解析Spring EL表示式,解析"#"符號(可以進行運算,可以寫某個bean的名字)
value = evaluateBeanDefinitionString(strVal, bd);
}
TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
try {
// 把value從descriptor.getTypeDescriptor()型別轉化為type類
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()));
}
}
// 沒有使用@Value註解
// 要注入的依賴的型別是不是一個Map、Array、Collection
Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);
if (multipleBeans != null) {
return multipleBeans;
}
// 通過type找,可能找到多個
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;
// 根據type找到了多個
if (matchingBeans.size() > 1) {
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.getBean(beanName);建立bean物件
instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this);
}
Object result = instanceCandidate;
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);
}
}
- 先判斷是不是Shortcut,如果是那麼可以理解beanName直接從beanFactory中拿到一個bean
// 如果DependencyDescriptor是一個ShortcutDependencyDescriptor,
// 那麼會直接理解beanName從beanFactory中拿到一個bean,
// 在利用@Autowired註解來進行依賴注入時會利用ShortcutDependencyDescriptor來進行依賴注入的快取,
// 表示當解析完某個依賴資訊後,會把依賴的bean的beanName快取起來
Object shortcut = descriptor.resolveShortcut(this);
if (shortcut != null) {
return shortcut;
}
//------------------------------------------------------------------------------
@Override
public Object resolveShortcut(BeanFactory beanFactory) {
return beanFactory.getBean(this.shortcut, this.requiredType);
}
- 判斷@Value註解是否存在,如果存在獲取並解析descriptor上的@Value註解,並進行解析返回
// 獲取@Value註解中所配置的值
Object value = getAutowireCandidateResolver().getSuggestedValue(descriptor); // 是否通過@Value註解指定了值
if (value != null) {
if (value instanceof String) {
// 先進行佔位符的填充,解析"$"符號
String strVal = resolveEmbeddedValue((String) value);
BeanDefinition bd = (beanName != null && containsBean(beanName) ?
getMergedBeanDefinition(beanName) : null);
// 解析Spring EL表示式,解析"#"符號(可以進行運算,可以寫某個bean的名字)
value = evaluateBeanDefinitionString(strVal, bd);
}
TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
try {
// 把value從descriptor.getTypeDescriptor()型別轉化為type類
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的型別
- descriptor的型別為Collection,或者map則直接返回map的value或者map
// 沒有使用@Value註解
// 要注入的依賴的型別是不是一個Map、Array、Collection
Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);
if (multipleBeans != null) {
return multipleBeans;
}
- 呼叫findAutowireCandidates(beanName, type, descriptor),該方法返回一個Map,表示會根據type去找bean,Map的key為beanName,Map的value為物件(注意可能是bena的物件,也可能是某個bean的class物件,因為該方法只負責根據型別找到對應的bean,如果該bean還沒有例項化,那麼該方法不負責去例項化,只返回該bean對應的Class物件,表示這個bean也是結果之一)
// 根據requiredType尋找自動匹配的候選者bean
protected Map<String, Object> findAutowireCandidates(
@Nullable String beanName, Class<?> requiredType, DependencyDescriptor descriptor) {
// 根據requiredType找到candidateNames,表示根據type找到了候選beanNames
// Ancestors是祖先的意思,所以這個方法是去當前beanfactory以及祖先beanfactory中去找型別為requiredType的bean的名字
String[] candidateNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
this, requiredType, true, descriptor.isEager());
Map<String, Object> result = new LinkedHashMap<>(candidateNames.length);
// 先從resolvableDependencies
for (Map.Entry<Class<?>, Object> classObjectEntry : this.resolvableDependencies.entrySet()) {
Class<?> autowiringType = classObjectEntry.getKey();
// requiredType是autowiringType的子類
// 也就是,某個bean中的屬性的型別是requiredType,是resolvableDependencies中的子類
if (autowiringType.isAssignableFrom(requiredType)) {
// 是resolvableDependencies中的子類所存的物件
Object autowiringValue = classObjectEntry.getValue();
autowiringValue = AutowireUtils.resolveAutowiringValue(autowiringValue, requiredType);
if (requiredType.isInstance(autowiringValue)) {
// 把resolvableDependencies中儲存的物件作為當前屬性的一個候選者
result.put(ObjectUtils.identityToString(autowiringValue), autowiringValue);
break;
}
}
}
// 對候選bean進行過濾,首先候選者不是自己,然後候選者是支援自動注入給其他bean的
for (String candidate : candidateNames) {
// isAutowireCandidate方法中會去判斷候選者是否和descriptor匹配
if (!isSelfReference(beanName, candidate) && isAutowireCandidate(candidate, descriptor)) {
addCandidateEntry(result, candidate, descriptor, requiredType);
}
}
if (result.isEmpty()) {
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);
}
}
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;
}
- 判斷根據type有沒有找到bean
- 如果沒有找到,判斷是不是isRequired
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
if (matchingBeans.isEmpty()) {
if (isRequired(descriptor)) {
raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
}
return null;
}
- 如果找到判斷是否超過一個,如果只有一個則則直接返回該bean,如果是Class物件,則呼叫getBean生成該bean物件
- 超過一個則呼叫determineAutowireCandidate(matchingBeans, descriptor)
// 根據type找到了多個
if (matchingBeans.size() > 1) {
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();
}
在找到多個的情況下呼叫determineAutowireCandidate(matchingBeans, descriptor)
protected String determineAutowireCandidate(Map<String, Object> candidates, DependencyDescriptor descriptor) {
Class<?> requiredType = descriptor.getDependencyType();
// 取@Primary的bean
String primaryCandidate = determinePrimaryCandidate(candidates, requiredType);
if (primaryCandidate != null) {
return primaryCandidate;
}
// 取優先順序最高的bean
String priorityCandidate = determineHighestPriorityCandidate(candidates, requiredType);
if (priorityCandidate != null) {
return priorityCandidate;
}
// Fallback
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;
}
- 從多個Bean中選擇被@Primary標註了的Bean,如果有多個@Primary會報錯
String primaryCandidate = determinePrimaryCandidate(candidates, requiredType);
if (primaryCandidate != null) {
return primaryCandidate;
}
//---------------------------------------------------------------------
protected String determinePrimaryCandidate(Map<String, Object> candidates, Class<?> requiredType) {
String primaryBeanName = null;
for (Map.Entry<String, Object> entry : candidates.entrySet()) {
String candidateBeanName = entry.getKey();
Object beanInstance = entry.getValue();
// 當前candidateBean是否@Primary
if (isPrimary(candidateBeanName, beanInstance)) {
if (primaryBeanName != null) {
boolean candidateLocal = containsBeanDefinition(candidateBeanName);
boolean primaryLocal = containsBeanDefinition(primaryBeanName);
if (candidateLocal && primaryLocal) {
throw new NoUniqueBeanDefinitionException(requiredType, candidates.size(),
"more than one 'primary' bean found among candidates: " + candidates.keySet());
}
else if (candidateLocal) {
primaryBeanName = candidateBeanName;
}
}
else {
primaryBeanName = candidateBeanName;
}
}
}
return primaryBeanName;
}
- 如果沒有@Primary,那麼則看Bean上是否通過@Priority定義了優先順序,如果定義了則獲取優先順序最高的Bean
// 取優先順序最高的bean
String priorityCandidate = determineHighestPriorityCandidate(candidates, requiredType);
if (priorityCandidate != null) {
return priorityCandidate;
}
- 如果沒有優先順序,那麼使用descriptor.getDependencyName()來確定一個唯一的Bean
- 判斷是否找到唯一的Bean
- 找到後如果不是Class物件直接返回,如果是就通過getBean獲取
- 如果沒有找到,判斷是否isRequired,如果是報錯,不是就返回null
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;
}
}
- 整體流程
相關文章
- Spring原始碼系列:依賴注入(二)createBeanSpring原始碼依賴注入Bean
- Laravel 依賴注入原始碼解析Laravel依賴注入原始碼
- spring原始碼解析之IOC容器(三)——依賴注入Spring原始碼依賴注入
- 死磕Spring原始碼-依賴注入Spring原始碼依賴注入
- Spring原始碼系列:依賴注入-引言Spring原始碼依賴注入
- Spring原始碼系列:依賴注入(三)-屬性注入Spring原始碼依賴注入
- Spring原始碼系列:依賴注入(一)getBeanSpring原始碼依賴注入Bean
- Spring原始碼系列:依賴注入(四)-總結Spring原始碼依賴注入
- Spring 原始碼分析之 bean 依賴注入原理(注入屬性)Spring原始碼Bean依賴注入
- Spring原始碼分析(二)bean的例項化和IOC依賴注入Spring原始碼Bean依賴注入
- Spring依賴注入Spring依賴注入
- Spring依賴注入---Spring依賴注入
- Spring IOC——依賴注入Spring依賴注入
- Spring 依賴注入 DISpring依賴注入
- spring 的依賴注入Spring依賴注入
- React 原始碼中的依賴注入方法React原始碼依賴注入
- Android依賴注入Dagger的使用和原始碼解析(上篇)Android依賴注入原始碼
- Spring系列.依賴注入配置Spring依賴注入
- Spring.Net 依賴注入Spring依賴注入
- 大白話spring依賴注入Spring依賴注入
- Spring 依賴注入的理解Spring依賴注入
- Spring原始碼--debug分析迴圈依賴--構造器注入Spring原始碼
- .NET 透過原始碼深究依賴注入原理原始碼依賴注入
- JavaScript中依賴注入詳細解析JavaScript依賴注入
- 解析依賴注入(DI)的本質依賴注入
- spring框架學習 依賴注入Spring框架依賴注入
- Spring的依賴注入的方式Spring依賴注入
- spring 依賴注入的學習Spring依賴注入
- Spring依賴注入原理學習Spring依賴注入
- Spring學習(三)依賴注入Spring依賴注入
- spring原始碼深度解析— IOC 之 迴圈依賴處理Spring原始碼
- 小白都能看懂的 Spring 原始碼揭祕之依賴注入(DI)原始碼分析Spring原始碼依賴注入
- ASP.NET Core - 依賴注入(二)ASP.NET依賴注入
- Spring Ioc原始碼分析系列--自動注入迴圈依賴的處理Spring原始碼
- Spring 控制反轉和依賴注入Spring依賴注入
- 分解uber依賴注入庫dig-原始碼分析依賴注入原始碼
- .net core 原始碼分析(9) 依賴注入(DI)-Dependency Injection原始碼依賴注入
- Spring系列第八講 依賴注入之手動注入Spring依賴注入