你所不知道的Spring的@Autowired實(shí)現(xiàn)細(xì)節(jié)分析
前言
相信很多Java開(kāi)發(fā)都遇到過(guò)一個(gè)面試題:Resource和Autowired的區(qū)別是什么?這個(gè)問(wèn)題的答案相信基本都清楚,但是這兩者在Spring中是如何實(shí)現(xiàn)的呢?這就要分析Spring源碼才能知道了。友情提示:本篇主要是講解Autowired的實(shí)現(xiàn)原理,不會(huì)分析Spring初始化的過(guò)程,不熟悉的讀者可以先閱讀筆者之前的一篇文章《這一次搞懂Spring的Bean實(shí)例化原理》。
正文
在Spring Bean的整個(gè)創(chuàng)建過(guò)程中會(huì)調(diào)用很多BeanPostProcessor接口的的實(shí)現(xiàn)類:

上圖是我整理的Spring Bean的創(chuàng)建過(guò)程及整個(gè)過(guò)程中各個(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不為空,就說(shuō)明構(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)造方法、普通方法),也就是通過(guò)構(gòu)造方法注入,如果沒(méi)有找到則通過(guò)反射調(diào)用無(wú)參構(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方法,通過(guò)這個(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)用后可以看到是通過(guò)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;
// 依賴注入過(guò)程,@Autowired的支持
PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
if (pvsToUse == null) {
if (filteredPds == null) {
filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
}
// 老版本用這個(gè)完成依賴注入過(guò)程,@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)注入沒(méi)錯(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 id="a" class="com.A" autowire="byName"/> <bean id="b" class="com.B" autowire="byType"/> </beans>
頭文件中的default-autowire屬性就是開(kāi)啟全局自動(dòng)注入,而bean標(biāo)簽上的autowire則是特定針對(duì)當(dāng)前bean的,會(huì)覆蓋全局配置。這樣我們配置后,bean標(biāo)簽就無(wú)需配置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í)表示將通過(guò)構(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)上很多人在爭(zhēng)論@Autowired是自動(dòng)注入還是手動(dòng)注入,我個(gè)人認(rèn)為都算自動(dòng)注入,不能說(shuō)它沒(méi)有進(jìn)入這段邏輯就不能叫自動(dòng)注入,只是它以另外一種方式實(shí)現(xiàn)了,至少也沒(méi)有讓我們自己手動(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;
// 依賴注入過(guò)程,@Autowired的支持
PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
if (pvsToUse == null) {
if (filteredPds == null) {
filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
}
// 老版本用這個(gè)完成依賴注入過(guò)程,@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ì)象放入到緩存,這里就是從緩存中拿到值,注入則是通過(guò)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ì)象,然后通過(guò)beanFactory.resolveDependency解析拿到對(duì)應(yīng)的實(shí)例,最后通過(guò)反射注入即可。
因此我們主要看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ì)象,通過(guò)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);
}
}
這里面首先是通過(guò) getAutowireCandidateResolver().getSuggestedValue(descriptor)拿到@Value注解的值,然后通過(guò)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));
}
}
首先通過(guò)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ì)象,通過(guò)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ò)。
若沒(méi)有標(biāo)注@Primary注解,則判斷是否指定了優(yōu)先級(jí),且只能是通過(guò)@Priority注解指定的,@Order不支持。
上述都沒(méi)有拿到合適的Bean則通過(guò)屬性名稱獲取Bean。
拿到對(duì)應(yīng)的實(shí)例后,最后進(jìn)行反射注入即可。以上就是@Autowired的實(shí)現(xiàn)細(xì)節(jié)。
總結(jié)
本篇從源碼角度詳細(xì)分析了@Autowired的實(shí)現(xiàn)細(xì)節(jié),只有真正閱讀了源碼才能了解更多的細(xì)節(jié),在開(kāi)發(fā)中更加清楚如何注入多個(gè)實(shí)例以及如何指定注入的優(yōu)先級(jí),同時(shí)在面試中也能更有理有據(jù),而不是統(tǒng)一的大眾回答,先根據(jù)byType,再根據(jù)byName。另外對(duì)于方法注入和@Resource注解的處理本篇沒(méi)有涉及,但是相信看完本文讀者自己也能輕松分析這部分源碼。
相關(guān)文章
Mybatis Plus條件構(gòu)造器ConditionConstructor用法實(shí)例解析
這篇文章主要介紹了Mybatis Plus條件構(gòu)造器ConditionConstructor用法實(shí)例解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-08-08
Mybatis?plus邏輯刪除注解@TableLogic的使用
本文主要介紹了Mybatis?plus邏輯刪除注解@TableLogic,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-01-01
Java IO中字節(jié)流復(fù)制圖片實(shí)現(xiàn)代碼
這篇文章主要介紹了Java IO中字節(jié)流復(fù)制圖片實(shí)現(xiàn)代碼的相關(guān)資料,需要的朋友可以參考下2017-04-04
JavaWeb中JavaMail創(chuàng)建郵件和發(fā)送郵件
這篇文章主要介紹了JavaWeb中JavaMail創(chuàng)建郵件和發(fā)送郵件,較為詳細(xì)的分析了JavaMail發(fā)送郵件的用法,是非常實(shí)用的技巧,需要的朋友可以參考下2015-12-12
定時(shí)任務(wù)@Scheduled用法及其參數(shù)使用
這篇文章主要介紹了定時(shí)任務(wù)@Scheduled用法及其參數(shù)使用,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-08-08

