詳解Spring中@Autowire,@Value 注解實(shí)現(xiàn)原理
來源:blog.csdn.net/u013202238/article/details/107879726
本文主要基于SpringBoot-2.3.3.RELEASE, Spring-5.2.8.RELEASE 講解.
Spring中@Autowire,@Value 注解實(shí)現(xiàn)原理,將這兩個(gè)注解放到一塊講解主要是他們的實(shí)現(xiàn)基本一致。
本文涉及注解:@Autowire、@Value、@Qualifier、@Lazy、@Primary、@javax.annotation.Priority
相關(guān)類介紹
如下是幾個(gè)重要的相關(guān)類:
org.springframework.beans.factory.config.BeanPostProcessor org.springframework.beans.factory.support.MergedBeanDefinitionPostProcessor org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor org.s.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor org.s.beans.factory.annotation.InjectionMetadata.InjectedElement org.s.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.AutowiredFieldElement org.s.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.AutowiredMethodElement
BeanPostProcessor
BeanPostProcessor是一個(gè)接口類,所有的bean在初始時(shí)期都會經(jīng)過這個(gè)后置處理器,主要提供如下兩個(gè)接口方法,
public?interface?BeanPostProcessor?{
?@Nullable
?default?Object?postProcessBeforeInitialization(Object?bean,?String?beanName)?throws?BeansException?{
??return?bean;
?}
?@Nullable
?default?Object?postProcessAfterInitialization(Object?bean,?String?beanName)?throws?BeansException?{
??return?bean;
?}
}
1、postProcessBeforeInitialization方法在bean初始化方法之前執(zhí)行.例如bean實(shí)現(xiàn)了InitializingBean接口,會在InitializingBean#afterPropertiesSet方法之前執(zhí)行。(不完全是這樣,因?yàn)橐磩?chuàng)建bean時(shí),某個(gè)BeanPostProcessor實(shí)現(xiàn)類是否已經(jīng)注冊)
對于BeanPostProcessor#postProcessBeforeInitialization是否在@PostConstruct注解的初始化方法之前執(zhí)行,這是不確定的,因?yàn)锧PostConstruct初始化方法的執(zhí)行是通過InitDestroyAnnotationBeanPostProcessor實(shí)現(xiàn),并且InitDestroyAnnotationBeanPostProcessor通過重寫BeanPostProcessor#postProcessBeforeInitialization實(shí)現(xiàn)@PostConstruct功能,CommonAnnotationBeanPostProcessor通過繼承InitDestroyAnnotationBeanPostProcessor擁有了相同的能力,因此要看BeanPostProcessor 實(shí)現(xiàn)類被注冊的順序才能決定是否優(yōu)先于@PostConstruct注解的方式執(zhí)行。
2、postProcessAfterInitialization 方法在bean的初始化方法之后執(zhí)行。
3、BeanPostProcessor 的子類接口如下UML圖

4、AbstractAutowireCapableBeanFactory#initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd)源碼如下:
protected?Object?initializeBean(String?beanName,?Object?bean,?@Nullable?RootBeanDefinition?mbd)?{
?if?(System.getSecurityManager()?!=?null)?{
??AccessController.doPrivileged((PrivilegedActionMergedBeanDefinitionPostProcessor
@Autowire,@Value 的查找 就是AutowiredAnnotationBeanPostProcessor通過重寫該方法實(shí)現(xiàn)
public?interface?MergedBeanDefinitionPostProcessor?extends?BeanPostProcessor?{
?void?postProcessMergedBeanDefinition(RootBeanDefinition?beanDefinition,?Class>?beanType,?String?beanName);
?
?default?void?resetBeanDefinition(String?beanName)?{
?}
}
BeanDefinition主要封裝了bean的類信息,例如是否是單實(shí)例(Singleton),初始化方法名,依賴的bean名稱等等。
在bean對象被創(chuàng)建之前,如果一個(gè)bean的BeanDefinition是一個(gè)子類,會先合并父類BeanDefinition,最終返回一個(gè)合并后的RootBeanDefinition,MergedBeanDefinitionPostProcessor則是Spring提供給開發(fā)的接口,便于對合并后的RootBeanDefinition做自定義修改。在調(diào)用AbstractAutowireCapableBeanFactory#doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)時(shí)回調(diào)MergedBeanDefinitionPostProcessor#postProcessMergedBeanDefinition方法。擴(kuò)展:40 個(gè) SpringBoot 常用注解
InstantiationAwareBeanPostProcessor
看注釋
@Autowire,@Value 的賦值 就是AutowiredAnnotationBeanPostProcessor通過重寫postProcessProperties方法實(shí)現(xiàn)
public?interface?InstantiationAwareBeanPostProcessor?extends?BeanPostProcessor?{
????//創(chuàng)建bean對象實(shí)例之前執(zhí)行
?default?Object?postProcessBeforeInstantiation(Class>?beanClass,?String?beanName)?throws?BeansException?{
??return?null;
?}
????//創(chuàng)建bean對象實(shí)例之后執(zhí)行
?default?boolean?postProcessAfterInstantiation(Object?bean,?String?beanName)?throws?BeansException?{
??return?true;
?}
????//用于給bean對象中的成員屬性賦值
????//@Autowire,@Value的賦值就是AutowiredAnnotationBeanPostProcessor通過重寫該方法實(shí)現(xiàn)
?default?PropertyValues?postProcessProperties(PropertyValues?pvs,?Object?bean,?String?beanName)
???throws?BeansException?{
??return?null;
?}
?@Deprecated???//標(biāo)記為過時(shí)
?default?PropertyValues?postProcessPropertyValues(
???PropertyValues?pvs,?PropertyDescriptor[]?pds,?Object?bean,?String?beanName)?throws?BeansException?{
??return?pvs;
?}
}
AutowiredAnnotationBeanPostProcessor
@Autowire,@Value,@Lookup等注解功能都是由AutowiredAnnotationBeanPostProcessor實(shí)現(xiàn),在本文主要講解@Autowire,@Value注解功能實(shí)現(xiàn)原理。
AutowiredAnnotationBeanPostProcessor的繼承關(guān)系如下:

AutowiredAnnotationBeanPostProcessor的構(gòu)造方法如下:主要定義了@Autowire,@Value兩個(gè)注解是過濾目標(biāo)bean的條件,如果bean中的Field、Method被標(biāo)記這兩個(gè)注解,則需要為其注入對應(yīng)的bean或者屬性值。
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.
??}
?}
在實(shí)現(xiàn)@Autowire,@Value功能的過程中,AutowiredAnnotationBeanPostProcessor主要起到兩個(gè)作用。
1、重寫MergedBeanDefinitionPostProcessor#postProcessMergedBeanDefinition方法,反射遍歷beanClass中的所有Field和Method,查找bean中標(biāo)記有@Autowire,@Value的Field、Method,封裝到org.springframework.beans.factory.annotation.InjectionMetadata中。
保存在成員變量private final Map中。
AutowiredAnnotationBeanPostProcessor#postProcessMergedBeanDefinition 源碼:
@Override
public?void?postProcessMergedBeanDefinition(RootBeanDefinition?beanDefinition,?Class>?beanType,?String?beanName)?{
?InjectionMetadata?metadata?=?findAutowiringMetadata(beanName,?beanType,?null);
?metadata.checkConfigMembers(beanDefinition);
}
findAutowiringMetadata方法內(nèi)部會調(diào)用到AnnotationUtils#isCandidateClass(Class>, Class extends Annotation>)用于判斷某個(gè)類是否可能 被標(biāo)記指定的某個(gè)注解。源碼如下:
public?static?boolean?isCandidateClass(Class>?clazz,?Class?extends?Annotation>?annotationType)?{
?return?isCandidateClass(clazz,?annotationType.getName());
}
public?static?boolean?isCandidateClass(Class>?clazz,?String?annotationName)?{
????//如果注解所在包是java開頭,任何類上都可能標(biāo)記這個(gè)注解
?if?(annotationName.startsWith("java."))?{
??return?true;
?}
?//注解所在包不是java開頭的情況
?//可以認(rèn)為是自定義注解,例如Spring的@Service?@Autowired?@Value?對Spring來說就是其自定義注解
?//如果類的包是以java開頭,則不可能標(biāo)記自定義的注解
?if?(AnnotationsScanner.hasPlainJavaAnnotationsOnly(clazz))?{
??return?false;
?}
?return?true;
}
AnnotationsScanner.hasPlainJavaAnnotationsOnly(clazz)
static?boolean?hasPlainJavaAnnotationsOnly(Class>?type)?{
?return?(type.getName().startsWith("java.")?||?type?==?Ordered.class);
}
2、重寫InstantiationAwareBeanPostProcessor#postProcessProperties方法,遍歷injectionMetadataCache中的InjectionMetadata,調(diào)用org.springframework.beans.factory.annotation.InjectionMetadata#inject方法,為bean的@Autowire和@value屬性字段賦值。
AutowiredAnnotationBeanPostProcessor#postProcessProperties 源碼:
@Override
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;
}
InjectionMetadata里面有個(gè)abstract內(nèi)部類InjectionMetadata.InjectedElement,主要用于給Field或者M(jìn)ethod賦值。
AutowiredAnnotationBeanPostProcessor中有兩個(gè)私有內(nèi)部類分別繼承了InjectedElement。
AutowiredAnnotationBeanPostProcessor.AutowiredFieldElement: 通過反射給Field賦值.AutowiredAnnotationBeanPostProcessor.AutowiredMethodElement: 通過反射調(diào)用setter Method賦值.
AutowiredAnnotationBeanPostProcessor.AutowiredFieldElement#inject源碼:
@Override
protected?void?inject(Object?bean,?@Nullable?String?beanName,?@Nullable?PropertyValues?pvs)?throws?Throwable?{
?Field?field?=?(Field)?this.member;
?Object?value;
?if?(this.cached)?{
??try?{
???value?=?resolvedCachedArgument(beanName,?this.cachedFieldValue);
??}
??catch?(NoSuchBeanDefinitionException?ex)?{
???//?Unexpected?removal?of?target?bean?for?cached?argument?->?re-resolve
???value?=?resolveFieldValue(field,?bean,?beanName);
??}
?}else?{
??value?=?resolveFieldValue(field,?bean,?beanName);
?}
?if?(value?!=?null)?{
?????//反射賦值
??ReflectionUtils.makeAccessible(field);
??field.set(bean,?value);
?}
}
AutowiredAnnotationBeanPostProcessor.AutowiredFieldElement#resolveFieldValue源碼:
private?Object?resolveFieldValue(Field?field,?Object?bean,?@Nullable?String?beanName)?{
?DependencyDescriptor?desc?=?new?DependencyDescriptor(field,?this.required);
?desc.setContainingClass(bean.getClass());
?Set?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;
????registerDependentBeans(beanName,?autowiredBeanNames);
????if?(autowiredBeanNames.size()?==?1)?{
?????String?autowiredBeanName?=?autowiredBeanNames.iterator().next();
?????if?(beanFactory.containsBean(autowiredBeanName)?&&
???????beanFactory.isTypeMatch(autowiredBeanName,?field.getType()))?{
??????cachedFieldValue?=?new?ShortcutDependencyDescriptor(
????????desc,?autowiredBeanName,?field.getType());
?????}
????}
???}
???this.cachedFieldValue?=?cachedFieldValue;
???this.cached?=?true;
??}
?}
?return?value;
}
方法內(nèi)部調(diào)用的beanFactory.resolveDependency(默認(rèn)DefaultListableBeanFactory)整體邏輯大概如下:
1.判斷Filed或者M(jìn)ethod上是否有@Lazy注解,如果存在則創(chuàng)建代理,實(shí)現(xiàn)懶加載。
2.不是懶加載,則判斷是否存在@Value注解,如果存在則獲取value值,最后通過PropertySourcesPropertyResolver#getProperty(java.lang.String, java.lang.Class解析屬性值(其實(shí)就是ConfigurableEnvironment中封裝的MutablePropertySources集合),獲取到屬性值之后還會通過SpringEL進(jìn)行一次解析。解析之后再由SimpleTypeConverter對象進(jìn)行一次數(shù)據(jù)類型轉(zhuǎn)換,轉(zhuǎn)為Filed所需要的類型返回.
3.如果不存在@Value注解,則是根據(jù)@Autowire注入bean, 從DefaultListableBeanFactory中變量所有的beanName,判斷對象類型是否和所需的相同,相同則保存beanName到List集合中(一個(gè)相同的接口可能出現(xiàn)多個(gè)實(shí)現(xiàn)類,所以用集合),
遍歷beanNames,判斷每個(gè)bean是否符合要求,如果存在@Qualifier會判斷名稱是否匹配,匹配則獲取對應(yīng)bean對象。如果沒有@Qualifier注解,則獲取全部的bean對象,封裝到Map中。 如果Map中存在多個(gè)實(shí)例對象,再判斷查找?guī)в蠤Primary注解的實(shí)現(xiàn)類,返回對象。同類型實(shí)現(xiàn)@Primary只能有一個(gè) 如果Map中存在多個(gè)實(shí)例對象,但是沒有@Primary注解,再比較是否有 @javax.annotation.Priority注解,選擇優(yōu)先高的返回,值越小優(yōu)先級越高。根據(jù)名稱匹配 不符合以上規(guī)則,則拋出異常信息,出現(xiàn)多個(gè)bean實(shí)現(xiàn)。
Spring中依賴注入Bean的匹配邏輯如下
DefaultListableBeanFactory#determineAutowireCandidate
protected?String?determineAutowireCandidate(Map?candidates,?DependencyDescriptor?descriptor) ?{
?Class>?requiredType?=?descriptor.getDependencyType();
?String?primaryCandidate?=?determinePrimaryCandidate(candidates,?requiredType);
?if?(primaryCandidate?!=?null)?{
??return?primaryCandidate;
?}
?String?priorityCandidate?=?determineHighestPriorityCandidate(candidates,?requiredType);
?if?(priorityCandidate?!=?null)?{
??return?priorityCandidate;
?}
?//?Fallback
?for?(Map.Entry?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;
}
END
推薦閱讀 一鍵生成Springboot & Vue項(xiàng)目!【畢設(shè)神器】
Java可視化編程工具系列(一)
Java可視化編程工具系列(二)
順便給大家推薦一個(gè)GitHub項(xiàng)目,這個(gè) GitHub 整理了上千本常用技術(shù)PDF,絕大部分核心的技術(shù)書籍都可以在這里找到,
GitHub地址:https://github.com/javadevbooks/books
Gitee地址:https://gitee.com/javadevbooks/books
電子書已經(jīng)更新好了,你們需要的可以自行下載了,記得點(diǎn)一個(gè)star,持續(xù)更新中..

