成人在线亚洲_国产日韩视频一区二区三区_久久久国产精品_99国内精品久久久久久久

您的位置:首頁技術(shù)文章
文章詳情頁

你所不知道的Spring的@Autowired實(shí)現(xiàn)細(xì)節(jié)分析

瀏覽:86日期:2023-08-19 13:38:45

前言

相信很多Java開發(fā)都遇到過一個(gè)面試題:Resource和Autowired的區(qū)別是什么?這個(gè)問題的答案相信基本都清楚,但是這兩者在Spring中是如何實(shí)現(xiàn)的呢?這就要分析Spring源碼才能知道了。友情提示:本篇主要是講解Autowired的實(shí)現(xiàn)原理,不會(huì)分析Spring初始化的過程,不熟悉的讀者可以先閱讀筆者之前的一篇文章《這一次搞懂Spring的Bean實(shí)例化原理》。

正文

在Spring Bean的整個(gè)創(chuàng)建過程中會(huì)調(diào)用很多BeanPostProcessor接口的的實(shí)現(xiàn)類:

你所不知道的Spring的@Autowired實(shí)現(xiàn)細(xì)節(jié)分析

上圖是我整理的Spring Bean的創(chuàng)建過程及整個(gè)過程中各個(gè)BeanPostProcessor和回調(diào)的調(diào)用,右邊相同顏色的連線代表是同一組調(diào)用,主要看到AutowiredAnnotationBeanPostProcessor和CommonAnnotationBeanPostProcessor,前者就是支持 @Autowired和@Value注解,后者則是支持@PostConstruct、@PreDestroy、@Resource注解。先了解這兩個(gè)Processor的作用,下面從頭分析。

從圖中可以看到,在createBeanInstance方法中會(huì)調(diào)用SmartInstantiationAwareBeanPostProcessor類型的determineCandidateConstructors,這個(gè)方法是做什么的呢?看代碼:

protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) { ...... // Candidate constructors for autowiring? //尋找當(dāng)前正在實(shí)例化的bean中有@Autowired注解的構(gòu)造函數(shù) Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName); if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR || mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) { //如果ctors不為空,就說明構(gòu)造函數(shù)上有@Autowired注解 return autowireConstructor(beanName, mbd, ctors, args); } ...... // No special handling: simply use no-arg constructor. return instantiateBean(beanName, mbd); } protected Constructor<?>[] determineConstructorsFromBeanPostProcessors(@Nullable Class<?> beanClass, String beanName) throws BeansException { if (beanClass != null && hasInstantiationAwareBeanPostProcessors()) { for (BeanPostProcessor bp : getBeanPostProcessors()) { if (bp instanceof SmartInstantiationAwareBeanPostProcessor) { SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp; Constructor<?>[] ctors = ibp.determineCandidateConstructors(beanClass, beanName); if (ctors != null) { return ctors; } } } } return null; }

createBeanInstance方法是去實(shí)例化Bean,而調(diào)用AutowiredAnnotationBeanPostProcessor.determineCandidateConstructors的目的就是先去找到帶有@Autowired注解的構(gòu)造方法(自動(dòng)注入有三種模式:屬性、構(gòu)造方法、普通方法),也就是通過構(gòu)造方法注入,如果沒有找到則通過反射調(diào)用無參構(gòu)造實(shí)例化。平時(shí)我們基本上都是使用的屬性注入,所以一般都不會(huì)進(jìn)入determineCandidateConstructors方法,所以這里也不詳細(xì)闡述,感興趣的讀者可自行看看。

接著回到doCreateBean方法中,就可以看到調(diào)用了applyMergedBeanDefinitionPostProcessors方法:

protected void applyMergedBeanDefinitionPostProcessors(RootBeanDefinition mbd, Class<?> beanType, String beanName) { for (BeanPostProcessor bp : getBeanPostProcessors()) { if (bp instanceof MergedBeanDefinitionPostProcessor) { /** * CommonAnnotationBeanPostProcessor 支持了@PostConstruct,@PreDestroy,@Resource注解 * AutowiredAnnotationBeanPostProcessor 支持 @Autowired,@Value注解 */ MergedBeanDefinitionPostProcessor bdp = (MergedBeanDefinitionPostProcessor) bp; bdp.postProcessMergedBeanDefinition(mbd, beanType, beanName); } } }

這個(gè)方法本質(zhì)上就是調(diào)用MergedBeanDefinitionPostProcessor類型的postProcessMergedBeanDefinition方法,通過這個(gè)方法去收集@Autowired、@Resource等注解,這里主要分析AutowiredAnnotationBeanPostProcessor的實(shí)現(xiàn):

public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) { InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null); metadata.checkConfigMembers(beanDefinition); } private InjectionMetadata findAutowiringMetadata(String beanName, Class<?> clazz, @Nullable PropertyValues pvs) { // Fall back to class name as cache key, for backwards compatibility with custom callers. String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName()); // Quick check on the concurrent map first, with minimal locking. InjectionMetadata metadata = this.injectionMetadataCache.get(cacheKey); if (InjectionMetadata.needsRefresh(metadata, clazz)) { synchronized (this.injectionMetadataCache) { metadata = this.injectionMetadataCache.get(cacheKey); if (InjectionMetadata.needsRefresh(metadata, clazz)) { if (metadata != null) { metadata.clear(pvs); } //主要看這個(gè)方法 metadata = buildAutowiringMetadata(clazz); this.injectionMetadataCache.put(cacheKey, metadata); } } } return metadata; } private InjectionMetadata buildAutowiringMetadata(final Class<?> clazz) { List<InjectionMetadata.InjectedElement> elements = new ArrayList<>(); Class<?> targetClass = clazz; do { final List<InjectionMetadata.InjectedElement> currElements = new ArrayList<>(); // 找到帶有@Autowired注解的屬性并封裝為AnnotationAttributes ReflectionUtils.doWithLocalFields(targetClass, field -> { AnnotationAttributes ann = findAutowiredAnnotation(field); if (ann != null) { if (Modifier.isStatic(field.getModifiers())) { if (logger.isInfoEnabled()) { logger.info('Autowired annotation is not supported on static fields: ' + field); } return; } boolean required = determineRequiredStatus(ann); currElements.add(new AutowiredFieldElement(field, required)); } }); // 找到帶有@Autowired注解的方法并封裝為AnnotationAttributes ReflectionUtils.doWithLocalMethods(targetClass, method -> { Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method); if (!BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) { return; } AnnotationAttributes ann = findAutowiredAnnotation(bridgedMethod); if (ann != null && method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) { if (Modifier.isStatic(method.getModifiers())) { if (logger.isInfoEnabled()) { logger.info('Autowired annotation is not supported on static methods: ' + method); } return; } if (method.getParameterCount() == 0) { if (logger.isInfoEnabled()) { logger.info('Autowired annotation should only be used on methods with parameters: ' + method); } } boolean required = determineRequiredStatus(ann); PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz); currElements.add(new AutowiredMethodElement(method, required, pd)); } }); elements.addAll(0, currElements); targetClass = targetClass.getSuperclass(); } while (targetClass != null && targetClass != Object.class); return new InjectionMetadata(clazz, elements); }

收集的邏輯主要在findAutowiringMetadata方法中,層層調(diào)用后可以看到是通過findAutowiredAnnotation這個(gè)方法去找到帶有@Autowired和@Value注解的屬性和方法:

private final Set<Class<? extends Annotation>> autowiredAnnotationTypes = new LinkedHashSet<>(4); public AutowiredAnnotationBeanPostProcessor() { this.autowiredAnnotationTypes.add(Autowired.class); this.autowiredAnnotationTypes.add(Value.class); try { this.autowiredAnnotationTypes.add((Class<? extends Annotation>) ClassUtils.forName('javax.inject.Inject', AutowiredAnnotationBeanPostProcessor.class.getClassLoader())); logger.trace('JSR-330 ’javax.inject.Inject’ annotation found and supported for autowiring'); } catch (ClassNotFoundException ex) { // JSR-330 API not available - simply skip. } } private AnnotationAttributes findAutowiredAnnotation(AccessibleObject ao) { if (ao.getAnnotations().length > 0) { // autowiring annotations have to be local for (Class<? extends Annotation> type : this.autowiredAnnotationTypes) { AnnotationAttributes attributes = AnnotatedElementUtils.getMergedAnnotationAttributes(ao, type); if (attributes != null) { return attributes; } } } return null; }

最后將其封裝為AutowiredFieldElement和AutowiredMethodElement對(duì)象的list并連同Class一起封裝成InjectionMetadata返回,這就完成了相關(guān)注解的收集。

收集完成后在哪里使用呢?對(duì)Bean生命周期熟悉的讀者都知道,之后就會(huì)進(jìn)行依賴注入,自然相關(guān)的調(diào)用就在populateBean這個(gè)方法里:

protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) { ...... PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null); if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_NAME || mbd.getResolvedAutowireMode() == AUTOWIRE_BY_TYPE) { MutablePropertyValues newPvs = new MutablePropertyValues(pvs); // Add property values based on autowire by name if applicable. if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_NAME) { autowireByName(beanName, mbd, bw, newPvs); } // Add property values based on autowire by type if applicable. if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_TYPE) { autowireByType(beanName, mbd, bw, newPvs); } pvs = newPvs; } boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors(); boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE); PropertyDescriptor[] filteredPds = null; //重點(diǎn)看這個(gè)if代碼塊,重要程度 5 if (hasInstAwareBpps) { if (pvs == null) { pvs = mbd.getPropertyValues(); } for (BeanPostProcessor bp : getBeanPostProcessors()) { if (bp instanceof InstantiationAwareBeanPostProcessor) { InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp; // 依賴注入過程,@Autowired的支持 PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName); if (pvsToUse == null) { if (filteredPds == null) { filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching); } // 老版本用這個(gè)完成依賴注入過程,@Autowired的支持 pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName); if (pvsToUse == null) { return; } } pvs = pvsToUse; } } } if (needsDepCheck) { if (filteredPds == null) { filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching); } checkDependencies(beanName, mbd, filteredPds, pvs); } // xml中<property>標(biāo)簽的依賴注入 if (pvs != null) { applyPropertyValues(beanName, mbd, bw, pvs); } }

mbd.getResolvedAutowireMode() == AUTOWIRE_BY_NAME || mbd.getResolvedAutowireMode() == AUTOWIRE_BY_TYPE

很多讀者包括網(wǎng)上很多文章在看到這個(gè)判斷時(shí),都認(rèn)為自動(dòng)注入的邏輯就是這里,但實(shí)際上并不是,這里是自動(dòng)注入沒錯(cuò),但卻是針對(duì)以前xml配置,如下:

<?xml version='1.0' encoding='UTF-8'?> <beans xmlns='http://www.springframework.org/schema/beans' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xsi:schemaLocation=' http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd' default-autowire='byName'> <bean autowire='byName'/> <bean autowire='byType'/></beans>

頭文件中的default-autowire屬性就是開啟全局自動(dòng)注入,而bean標(biāo)簽上的autowire則是特定針對(duì)當(dāng)前bean的,會(huì)覆蓋全局配置。這樣我們配置后,bean標(biāo)簽就無需配置prototype子標(biāo)簽,也能自動(dòng)注入對(duì)應(yīng)的對(duì)象。這些屬性包含了以下幾個(gè)值:

no:默認(rèn)值。表示不進(jìn)行自動(dòng)注入。對(duì)應(yīng)BeanDefinition中autowireMode的值為 0。

byName:根據(jù)名稱進(jìn)行自動(dòng)注入。對(duì)應(yīng)BeanDefinition中autowireMode的值為1。

byType:根據(jù)類型進(jìn)行自動(dòng)注入,如果容器中找到兩個(gè)及以上符合該類型的Bean就將拋出異常。對(duì)應(yīng)BeanDefinition中autowireMode的值為2。

constructor:等同于byType,只是當(dāng)指定autowire=”constructor”時(shí)表示將通過構(gòu)造方法根據(jù)類型進(jìn)行自動(dòng)注入。對(duì)應(yīng)BeanDefinition中autowireMode的值為3。

這就是xml配置中的自動(dòng)注入,而我們使用@Autowired注解時(shí),BeanDefinition中autowireMode的值為 0,即表示不進(jìn)行自動(dòng)注入。插一句題外話,網(wǎng)上很多人在爭論@Autowired是自動(dòng)注入還是手動(dòng)注入,我個(gè)人認(rèn)為都算自動(dòng)注入,不能說它沒有進(jìn)入這段邏輯就不能叫自動(dòng)注入,只是它以另外一種方式實(shí)現(xiàn)了,至少也沒有讓我們自己手動(dòng)new并設(shè)置屬性。

那這另外一種方式是什么呢?就是下面這個(gè)代碼干的事:

if (hasInstAwareBpps) { if (pvs == null) { pvs = mbd.getPropertyValues(); } for (BeanPostProcessor bp : getBeanPostProcessors()) { if (bp instanceof InstantiationAwareBeanPostProcessor) { InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp; // 依賴注入過程,@Autowired的支持 PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName); if (pvsToUse == null) { if (filteredPds == null) { filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching); } // 老版本用這個(gè)完成依賴注入過程,@Autowired的支持 pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName); if (pvsToUse == null) { return; } } pvs = pvsToUse; } }}

可以看到這里又是調(diào)用了InstantiationAwareBeanPostProcessor類型的postProcessProperties和postProcessPropertyValues方法,后者是老版本中的實(shí)現(xiàn),已經(jīng)廢棄,所以直接看postProcessProperties,還是進(jìn)入到AutowiredAnnotationBeanPostProcessor類中:

public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) { InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs); try { metadata.inject(bean, beanName, pvs); } catch (BeanCreationException ex) { throw ex; } catch (Throwable ex) { throw new BeanCreationException(beanName, 'Injection of autowired dependencies failed', ex); } return pvs; }

findAutowiringMetadata這個(gè)方法不陌生的,剛剛已經(jīng)分析了,是去收集對(duì)應(yīng)注解并封裝為InjectionMetadata對(duì)象放入到緩存,這里就是從緩存中拿到值,注入則是通過inject實(shí)現(xiàn)的:

public void inject(Object target, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable { Collection<InjectedElement> checkedElements = this.checkedElements; Collection<InjectedElement> elementsToIterate = (checkedElements != null ? checkedElements : this.injectedElements); if (!elementsToIterate.isEmpty()) { for (InjectedElement element : elementsToIterate) { if (logger.isTraceEnabled()) { logger.trace('Processing injected element of bean ’' + beanName + '’: ' + element); } if(element.isField) { Field field = (Field)element.member; System.out.println('==IOC/DI===beanName==' + beanName + '==field[' + field.getName() +']-> getBean(' + field.getName() + ')'); } element.inject(target, beanName, pvs); } }}

最后就是調(diào)用element.inject實(shí)現(xiàn)注入,element我們剛剛也看到了,就是AutowiredFieldElement和AutowiredMethodElement,分別實(shí)現(xiàn)屬性注入和方法注入,這里我們看最常用的屬性注入就行了:

protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable { Field field = (Field) this.member; Object value; if (this.cached) { value = resolvedCachedArgument(beanName, this.cachedFieldValue); } else { 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(); try { // 找到依賴對(duì)象 value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter); } catch (BeansException ex) { throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(field), ex); } synchronized (this) { if (!this.cached) { if (value != null || this.required) { this.cachedFieldValue = desc; registerDependentBeans(beanName, autowiredBeanNames); if (autowiredBeanNames.size() == 1) { String autowiredBeanName = autowiredBeanNames.iterator().next(); if (beanFactory.containsBean(autowiredBeanName) && beanFactory.isTypeMatch(autowiredBeanName, field.getType())) { this.cachedFieldValue = new ShortcutDependencyDescriptor( desc, autowiredBeanName, field.getType()); } } } else { this.cachedFieldValue = null; } this.cached = true; } } } if (value != null) { ReflectionUtils.makeAccessible(field); field.set(bean, value); }}

這段代碼整體邏輯比較清晰,首先根據(jù)field創(chuàng)建一個(gè)依賴對(duì)象的抽象DependencyDescriptor對(duì)象,然后通過beanFactory.resolveDependency解析拿到對(duì)應(yīng)的實(shí)例,最后通過反射注入即可。

因此我們主要看resolveDependency方法中做了什么:

public Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName, @Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException { descriptor.initParameterNameDiscovery(getParameterNameDiscoverer()); 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) { result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter); } return result; }}

一般情況下,都是走的else分支并調(diào)用doResolveDependency方法:

public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName, @Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException { InjectionPoint previousInjectionPoint = ConstructorResolver.setCurrentInjectionPoint(descriptor); try { Object shortcut = descriptor.resolveShortcut(this); if (shortcut != null) { return shortcut; } Class<?> type = descriptor.getDependencyType(); Object value = getAutowireCandidateResolver().getSuggestedValue(descriptor); if (value != null) { 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())); } // 有多個(gè)實(shí)現(xiàn)類需要注入,特指注入的是數(shù)組、集合或者M(jìn)ap Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter); if (multipleBeans != null) { return multipleBeans; } // 找到依賴對(duì)象的所有實(shí)現(xiàn)類 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; // 依賴的對(duì)象有多個(gè)實(shí)例 if (matchingBeans.size() > 1) { // 根據(jù)@Primary、@Priority和名稱依次進(jìn)行匹配注入 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); } // 如果拿到的是class對(duì)象,通過getBean實(shí)例化返回 if (instanceCandidate instanceof Class) { 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); }}

這里面首先是通過 getAutowireCandidateResolver().getSuggestedValue(descriptor)拿到@Value注解的值,然后通過TypeConverter進(jìn)行轉(zhuǎn)換,默認(rèn)可轉(zhuǎn)換的類型是JDK和Spring內(nèi)置的一些類型,自然不包含我們自定義的類,所以如果不進(jìn)行擴(kuò)展在@Autowired注入我們自定義類對(duì)象時(shí)同時(shí)使用@Value注解是會(huì)報(bào)錯(cuò)的。

接著是調(diào)用resolveMultipleBeans方法實(shí)現(xiàn)對(duì)Map、List、數(shù)組等屬性的注入,本質(zhì)上還是調(diào)用findAutowireCandidates方法找到所有的實(shí)現(xiàn)類的對(duì)象裝入對(duì)應(yīng)的集合數(shù)組中,所以直接看findAutowireCandidates:

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); ...... for (String candidate : candidateNames) { if (!isSelfReference(beanName, candidate) && isAutowireCandidate(candidate, descriptor)) { addCandidateEntry(result, candidate, descriptor, requiredType); } } ...... return result;}private void addCandidateEntry(Map<String, Object> candidates, String candidateName, DependencyDescriptor descriptor, Class<?> requiredType) { if (descriptor instanceof MultiElementDescriptor) { Object beanInstance = descriptor.resolveCandidate(candidateName, requiredType, this); if (!(beanInstance instanceof NullBean)) { candidates.put(candidateName, beanInstance); } } else if (containsSingleton(candidateName) || (descriptor instanceof StreamDependencyDescriptor && ((StreamDependencyDescriptor) descriptor).isOrdered())) { Object beanInstance = descriptor.resolveCandidate(candidateName, requiredType, this); candidates.put(candidateName, (beanInstance instanceof NullBean ? null : beanInstance)); } else { candidates.put(candidateName, getType(candidateName)); }}

首先通過beanNamesForTypeIncludingAncestors方法拿到依賴類所有的實(shí)現(xiàn)類的beanName,然后調(diào)用addCandidateEntry將beanName及對(duì)應(yīng)的實(shí)例或者Class對(duì)象放入到Map中。

接著回到doResolveDependency方法中:

if (matchingBeans.size() > 1) { // 根據(jù)@Primary、@Priority和名稱依次進(jìn)行匹配注入 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);}// 如果拿到的是class對(duì)象,通過getBean實(shí)例化返回if (instanceCandidate instanceof Class) { instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this);}Object result = instanceCandidate;

如果只有一個(gè)實(shí)例則直接返回該實(shí)例,如果實(shí)現(xiàn)類有多個(gè)則調(diào)用determineAutowireCandidate進(jìn)行判斷該使用哪一個(gè)實(shí)例對(duì)象,判斷規(guī)則如下:

首先判斷實(shí)現(xiàn)類上是否有@Primary注解,找到一個(gè)則返回當(dāng)前實(shí)例,找到多個(gè)則報(bào)錯(cuò)。

若沒有標(biāo)注@Primary注解,則判斷是否指定了優(yōu)先級(jí),且只能是通過@Priority注解指定的,@Order不支持。

上述都沒有拿到合適的Bean則通過屬性名稱獲取Bean。

拿到對(duì)應(yīng)的實(shí)例后,最后進(jìn)行反射注入即可。以上就是@Autowired的實(shí)現(xiàn)細(xì)節(jié)。

總結(jié)

本篇從源碼角度詳細(xì)分析了@Autowired的實(shí)現(xiàn)細(xì)節(jié),只有真正閱讀了源碼才能了解更多的細(xì)節(jié),在開發(fā)中更加清楚如何注入多個(gè)實(shí)例以及如何指定注入的優(yōu)先級(jí),同時(shí)在面試中也能更有理有據(jù),而不是統(tǒng)一的大眾回答,先根據(jù)byType,再根據(jù)byName。另外對(duì)于方法注入和@Resource注解的處理本篇沒有涉及,但是相信看完本文讀者自己也能輕松分析這部分源碼。

標(biāo)簽: Spring
相關(guān)文章:
成人在线亚洲_国产日韩视频一区二区三区_久久久国产精品_99国内精品久久久久久久
日韩欧美国产精品| 国产午夜精品久久| 国产欧美日韩另类一区| 国产一区二区三区免费在线观看| 久久精品一区二区三区中文字幕| 亚洲欧洲www| 欧美日韩喷水| 久久精品视频在线免费观看| 成人aa视频在线观看| 欧美一区二区三区在线| 国产一区二区三区免费在线观看 | 国内精品第一页| 欧美在线观看视频在线| 日韩国产高清在线| 久久久久久久久久久一区| 亚洲自拍偷拍av| 亚洲国产欧洲综合997久久| 久久久精品黄色| 91同城在线观看| 久久蜜桃av一区精品变态类天堂 | 免费在线观看日韩欧美| 久久精品亚洲一区二区| 日韩影院精彩在线| 久久成人亚洲| 五月天网站亚洲| 久久久精品网| 水蜜桃久久夜色精品一区的特点 | 国产伦理一区| 亚洲成人av资源| 久久婷婷丁香| 日本aⅴ免费视频一区二区三区| 欧美性色黄大片手机版| 老汉av免费一区二区三区| 欧美日韩一区二区电影| 国产风韵犹存在线视精品| 日韩欧美中文字幕精品| 成人一级片网址| 亚洲精品一区二区三区在线观看| 亚洲欧洲美洲综合色网| 韩国自拍一区| 亚洲素人一区二区| 亚洲一区图片| 免费成人深夜小野草| 欧美丰满少妇xxxbbb| 91福利视频久久久久| 国产在线精品一区二区| 日韩色在线观看| 欧美国产三区| 亚洲婷婷综合久久一本伊一区| 亚洲国产第一| 亚洲成a人v欧美综合天堂| 欧美探花视频资源| 波多野结衣亚洲一区| 国产精品美女久久久久高潮| 欧美日一区二区在线观看| 亚洲男帅同性gay1069| 免费国产一区二区| 久久99精品国产.久久久久| 日韩免费一区二区三区在线播放| eeuss鲁片一区二区三区在线观看| 国产无一区二区| 亚洲国产精品第一区二区| 亚洲宅男天堂在线观看无病毒| 色婷婷综合久久久久中文一区二区| 国产一区二区女| 国产亚洲欧美激情| 中文有码久久| 日本三级韩国三级欧美三级| 欧美一区二区三区小说| 午夜精品区一区二区三| 一区二区三区.www| 欧美日韩一区在线| 豆国产96在线|亚洲| 国产精品你懂的| 91久久国产最好的精华液| 成人午夜看片网址| 亚洲欧美一区二区三区孕妇| 欧美三级一区二区| 91在线观看污| 一区二区三区电影在线播| 欧美日韩视频一区二区| 91丨porny丨在线| 亚洲已满18点击进入久久| 国产精品69毛片高清亚洲| 欧美韩国日本不卡| 老司机精品福利视频| av电影天堂一区二区在线观看| 一区二区三区四区高清精品免费观看 | 国产精品欧美久久久久无广告 | 欧美日韩一区不卡| 亚洲一级影院| 久久精品国产第一区二区三区| 久久免费看少妇高潮| 男人的天堂亚洲在线| 成人激情开心网| 亚洲高清不卡在线| 亚洲精品一区二区三区99| 香港久久久电影| 97久久精品人人做人人爽50路| 亚洲aaa精品| 久久一日本道色综合| 国产精品一国产精品k频道56| 国产精品一区二区无线| 亚洲精品视频自拍| 日韩一区二区三区视频| 性刺激综合网| 91在线国产观看| 免费看精品久久片| 欧美国产精品一区二区三区| 欧美性猛片aaaaaaa做受| 欧美日韩国产高清视频| 久久99蜜桃精品| 亚洲人成网站影音先锋播放| 日韩欧美一二三四区| 久久精品国产综合精品| 欧美凹凸一区二区三区视频| 日本麻豆一区二区三区视频| 亚洲国产精品ⅴa在线观看| 欧美日韩精品一区二区三区四区| 一区国产精品| 成人性色生活片| 婷婷综合另类小说色区| 国产精品视频在线看| 91精品国产福利| 久久久久国产精品一区三寸| 亚洲午夜精品久久久久久app| 国内精品国产成人国产三级粉色 | 男人天堂欧美日韩| 红桃视频国产一区| 国产成人亚洲精品青草天美| 亚洲成人免费av| 国产精品热久久久久夜色精品三区| 欧美一级片在线看| 久久婷婷丁香| 亚洲精品一品区二品区三品区| 99久久精品免费看国产免费软件| 奇米精品一区二区三区四区| 亚洲综合一区在线| 国产精品网站在线| 精品久久久久久久人人人人传媒 | 欧美日韩免费在线视频| 日韩午夜电影| 99v久久综合狠狠综合久久| 国模套图日韩精品一区二区| 亚洲高清视频在线| 亚洲欧洲av一区二区三区久久| 久久色成人在线| 91精品中文字幕一区二区三区| 91久久线看在观草草青青| 亚洲成人原创| 国产精品草草| 欧美伊人影院| 成人av免费在线| 国产精品一区二区视频| 久久99精品久久只有精品| 午夜精品久久久久| 一区二区三区成人在线视频 | 国内精品在线播放| 日韩电影在线免费看| 一二三区精品视频| 中文字幕av一区 二区| 久久久蜜桃精品| 精品国产三级a在线观看| 欧美一级在线观看| 欧美日韩国产不卡| 欧美三级中文字幕| 在线观看免费一区| 久久精选视频| 一本一道综合狠狠老| 裸体素人女欧美日韩| 国产精品美女xx| 国产精品乱码| 亚洲在线不卡| 亚洲一区国产一区| 国产精品欧美久久| 一区二区三区视频在线播放| 亚洲精品1区2区| 亚洲欧洲精品一区二区三区波多野1战4 | 韩国成人在线视频| 久久精品国产澳门| 男男成人高潮片免费网站| 美女尤物国产一区| 乱一区二区av| 韩国精品久久久| 福利一区福利二区| 99精品桃花视频在线观看| 91香蕉视频污在线| 欧美aⅴ99久久黑人专区| 欧美黄色一级视频| 欧美区日韩区| 欧美午夜a级限制福利片| 韩国久久久久| 国产欧美二区| 欧美综合国产| 91成人在线观看喷潮| 在线观看日产精品| 欧美一区二区三区喷汁尤物| 日韩精品中文字幕一区| 久久精品夜色噜噜亚洲aⅴ| 中文字幕成人在线观看|