<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          詳解Spring中@Autowire,@Value 注解實(shí)現(xiàn)原理

          共 5446字,需瀏覽 11分鐘

           ·

          2021-12-24 08:39

          來源: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((PrivilegedAction)?()?->?{
          ???invokeAwareMethods(beanName,?bean);
          ???return?null;
          ??},?getAccessControlContext());
          ?}else?{
          ?????//判斷是否實(shí)現(xiàn)了Aware接口,執(zhí)行子類接口方法,
          ?????//此時(shí)只有:BeanNameAware,BeanClassLoaderAware,BeanFactoryAware
          ??invokeAwareMethods(beanName,?bean);?
          ?}
          ?Object?wrappedBean?=?bean;
          ?if?(mbd?==?null?||?!mbd.isSynthetic())?{
          ?????//調(diào)用BeanPostProcessor#postProcessBeforeInitialization
          ?????//ApplicationContextAwareProcessor#postProcessBeforeInitialization
          ?????//實(shí)現(xiàn)EnvironmentAware,..ApplicationContextAware等Aware的回調(diào).
          ??wrappedBean?=?applyBeanPostProcessorsBeforeInitialization(wrappedBean,?beanName);
          ?}
          ?try?{
          ?????//如果bean實(shí)現(xiàn)了InitializingBean接口則執(zhí)行接口的afterPropertiesSet方法
          ??invokeInitMethods(beanName,?wrappedBean,?mbd);
          ?}
          ?catch?(Throwable?ex)?{
          ??throw?new?BeanCreationException(
          ????(mbd?!=?null???mbd.getResourceDescription()?:?null),
          ????beanName,?"Invocation?of?init?method?failed",?ex);
          ?}
          ?if?(mbd?==?null?||?!mbd.isSynthetic())?{
          ??wrappedBean?=?applyBeanPostProcessorsAfterInitialization(wrappedBean,?beanName);
          ?}
          ?return?wrappedBean;
          }

          MergedBeanDefinitionPostProcessor

          @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)
          ?????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 injectionMetadataCache = new ConcurrentHashMap<>(256);中。

          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)用于判斷某個(gè)類是否可能 被標(biāo)記指定的某個(gè)注解。源碼如下:

          public?static?boolean?isCandidateClass(Class?clazz,?Class?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, boolean)解析屬性值(其實(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ù)更新中..



          瀏覽 100
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評論
          圖片
          表情
          推薦
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                    <th id="afajh"><progress id="afajh"></progress></th>
                    日韩中AV无码毛片 | 小香蕉伊人| 午夜福利天天射天天操 | 国产一级二级在线观看 | 青青草原在线免费 |