最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Spring源碼解析 Bean屬性填充

 更新時間:2022年07月07日 09:36:56   作者:? 碼農(nóng)參上??  
這篇文章主要介紹了Spring源碼解析 Bean屬性填充,文章圍繞主題展開想詳細(xì)的內(nèi)容詳情,具有一定的參考價值,需要的小伙伴可以參考一下

前言

上一篇文章中,我們分析了Spring中Bean的實例化過程,在結(jié)尾我們知道了雖然bean的實例化完成了,但是其中的屬性還沒有被注入,今天我們就接著來分析屬性是如何被注入的。

屬性填充

實例化完成后,回到上面第3條的doCreateBean方法中,看一下用BeanWrapper產(chǎn)生的原生對象,里面dao這個屬性還是null值。

回歸一下之前的代碼,接下來要調(diào)用populateBean方法進(jìn)行屬性的填充:

Object exposedObject = bean;
try {
  populateBean(beanName, mbd, instanceWrapper);
  exposedObject = initializeBean(beanName, exposedObject, mbd);
}

看一下populateBean中的核心代碼:

for (BeanPostProcessor bp : getBeanPostProcessors()) {
  if (bp instanceof InstantiationAwareBeanPostProcessor) {
    InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
    pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
    if (pvs == null) {
      return;
    }
  }
}

這里通過getBeanPostProcessors方法獲得當(dāng)前注冊的所有后置處理器,如果屬于InstantiationAwareBeanPostProcessor類型,則調(diào)用它的postProcessPropertyValues方法。通過遍歷,可以知道當(dāng)前spring中存在7個后置處理器:

我們主要來看一下AutowiredAnnotationBeanPostProcessor,因為它負(fù)責(zé)對添加了 @Autowired、@Value等注解的屬性進(jìn)行依賴的填充。進(jìn)入它的postProcessPropertyValues方法:

public PropertyValues postProcessPropertyValues(
  PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeanCreationException {
  InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
  try {
    metadata.inject(bean, beanName, pvs);
  }
 //異常處理代碼省略...
  return pvs;
}

這里的InjectionMetadata可以理解為要注入的屬性的元數(shù)據(jù),在它里面維護(hù)了一個Collection,來存放所有需要注入的bean:

private final Collection<InjectedElement> injectedElements;

進(jìn)入findAutowiringMetadata方法:

private InjectionMetadata findAutowiringMetadata(String beanName, Class<?> clazz, @Nullable PropertyValues pvs) {
 String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName());
 InjectionMetadata metadata = this.injectionMetadataCache.get(cacheKey);
  //省略非重要代碼...
 return metadata;
}

在執(zhí)行完這一步后,就把需要填充的屬性放進(jìn)了剛才提到的injectedElements中:

接下來,繼續(xù)執(zhí)行InjectionMetadatainject方法,在其中遍歷所有需要注入的屬性的列表,遍歷調(diào)用AutowiredAnnotationBeanPostProcessor的inject方法:

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 {//用beanFactory解決依賴
          value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);
        }
   //后面代碼省略...

這里創(chuàng)建了一個DependencyDescriptor,用來維護(hù)注入屬性與它的容器類containingClass的關(guān)系,里面最重要的就是存放了注入屬性的類型、名稱,以及containingClass的類型等信息。

調(diào)用resolveDependency方法,其中沒有做什么實質(zhì)性的工作,繼續(xù)調(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()));
    }

    Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);
    if (multipleBeans != null) {
      return multipleBeans;
    }
    //把匹配的值和類型拿出來,放到一個map中
    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;
    //如果有超過一個匹配的,可能會有錯誤
    if (matchingBeans.size() > 1) {
      autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor);
      if (autowiredBeanName == null) {
        if (isRequired(descriptor) || !indicatesMultipleBeans(type)) {
          return descriptor.resolveNotUnique(type, matchingBeans);
        }
        else {
          return null;
        }
      }
      instanceCandidate = matchingBeans.get(autowiredBeanName);
    }
    else {
      Map.Entry<String, Object> entry = matchingBeans.entrySet().iterator().next();
      autowiredBeanName = entry.getKey();
      instanceCandidate = entry.getValue();
    }

    if (autowiredBeanNames != null) {
      //把找到的bean的名字放到set中
      autowiredBeanNames.add(autowiredBeanName);
    }
    if (instanceCandidate instanceof Class) {
      // 實際獲取注入的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);
  }
}

通過findAutowireCandidates方法,獲取與注入屬性匹配的值和類型,放到一個Map當(dāng)中,再通過它的beanName,調(diào)用resolveCandidate方法,實際獲取注入的bean實例。這一操作底層調(diào)用的也是BeanFactory的getBean方法。

回到inject方法,使用反射將注入的bean實例賦值給屬性:

ReflectionUtils.makeAccessible(field);
field.set(bean, value);

在執(zhí)行完populateBean方法后,依賴的屬性已經(jīng)被注入成功了。

執(zhí)行回調(diào)方法及后置處理器

在bean實例化完成后,執(zhí)行各種回調(diào)和后置管理器方法:

protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
  if (System.getSecurityManager() != null) {
    AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
      invokeAwareMethods(beanName, bean);
      return null;
    }, getAccessControlContext());
  }
  else {
    //若bean實現(xiàn)了BeanNameAware、BeanClassLoaderAware、BeanFactoryAware接口,執(zhí)行回調(diào)方法
    invokeAwareMethods(beanName, bean);
  }

  Object wrappedBean = bean;
  if (mbd == null || !mbd.isSynthetic()) {
    //執(zhí)行所有后置處理器的before方法
    wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
  }

  try {
    //執(zhí)行bean生命周期回調(diào)中的init-method
    //若bean實現(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()) {
    //執(zhí)行所有后置處理器的after方法
    wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
  }

  return wrappedBean;
}

具體執(zhí)行內(nèi)容:

  • 1、若bean實現(xiàn)了BeanNameAwareBeanClassLoaderAware、BeanFactoryAware接口,執(zhí)行回調(diào)方法
  • 2、執(zhí)行所有后置處理器的postProcessBeforeInitialization方法
  • 3、執(zhí)行bean生命周期回調(diào)中的init-method,若bean實現(xiàn)了InitializingBean接口,執(zhí)行afterPropertiesSet方法
  • 4、執(zhí)行所有后置處理器的postProcessAfterInitialization方法

在這一步完成后,bean的實例化過程全部結(jié)束。最后執(zhí)行一下refresh方法中的finishRefresh方法,進(jìn)行廣播事件等操作。到這,一個完整的AnnotationConfigApplicationContext初始化就完成了。

到此這篇關(guān)于Spring源碼解析 Bean屬性填充的文章就介紹到這了,更多相關(guān)Spring Bean屬性填充內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • java中object類實例分析

    java中object類實例分析

    這篇文章主要介紹了java中object類實例分析,具有一定借鑒價值,需要的朋友可以參考下。
    2017-12-12
  • java方法重寫和super關(guān)鍵字實例詳解

    java方法重寫和super關(guān)鍵字實例詳解

    這篇文章主要介紹了java方法重寫和super關(guān)鍵字實例詳解的相關(guān)資料,需要的朋友可以參考下
    2017-03-03
  • SpringBoot基于Redis實現(xiàn)token的在線續(xù)期的實踐

    SpringBoot基于Redis實現(xiàn)token的在線續(xù)期的實踐

    本文主要介紹了使用Redis實現(xiàn)JWT令牌在線續(xù)期的方案,通過在線續(xù)期token,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2024-12-12
  • SpringBoot持久化層操作支持技巧

    SpringBoot持久化層操作支持技巧

    這篇文章主要介紹了SpringBoot持久化層操作支持技巧,需要的朋友可以參考下
    2017-10-10
  • SpringBoot中讀取配置的七種方法總結(jié)

    SpringBoot中讀取配置的七種方法總結(jié)

    在Spring Boot應(yīng)用中,讀取配置是一項基礎(chǔ)且重要的任務(wù),Spring Boot提供了多種靈活的方式來讀取配置,以滿足不同場景下的需求,本文將詳細(xì)介紹Spring Boot中讀取配置的幾種常用方法,需要的朋友可以參考下
    2024-08-08
  • java中l(wèi)ambda表達(dá)式簡單用例

    java中l(wèi)ambda表達(dá)式簡單用例

    讓我們從最簡單的例子開始,來學(xué)習(xí)如何對一個string列表進(jìn)行排序。我們首先使用Java 8之前的方法來實現(xiàn)
    2016-09-09
  • Spring Bean實例化實現(xiàn)過程解析

    Spring Bean實例化實現(xiàn)過程解析

    這篇文章主要介紹了Spring Bean實例化實現(xiàn)過程解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-02-02
  • Java調(diào)用計算機(jī)攝像頭拍照實現(xiàn)過程解析

    Java調(diào)用計算機(jī)攝像頭拍照實現(xiàn)過程解析

    這篇文章主要介紹了Java調(diào)用計算機(jī)攝像頭拍照實現(xiàn)過程解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-05-05
  • Spring框架應(yīng)用的權(quán)限控制系統(tǒng)詳解

    Spring框架應(yīng)用的權(quán)限控制系統(tǒng)詳解

    在本篇文章里小編給大家整理的是關(guān)于基于Spring框架應(yīng)用的權(quán)限控制系統(tǒng)的研究和實現(xiàn),需要的朋友們可以學(xué)習(xí)下。
    2019-08-08
  • Java緩存框架之Caffeine源碼解析

    Java緩存框架之Caffeine源碼解析

    這篇文章主要介紹了Java緩存框架之Caffeine源碼解析,Caffeine?是一個基于Java?8的高性能本地緩存框架,其結(jié)構(gòu)和?Guava?Cache?基本一樣,api也一樣,基本上很容易就能替換,需要的朋友可以參考下
    2023-11-11

最新評論

阿尔山市| 临安市| 旺苍县| 英山县| 锡林郭勒盟| 稷山县| 金坛市| 枝江市| 石门县| 施甸县| 抚松县| 萍乡市| 茂名市| 姚安县| 民和| 临清市| 佛冈县| 福贡县| 大关县| 琼结县| 普格县| 吴川市| 通江县| 连城县| 梨树县| 陆丰市| 荆州市| 抚顺县| 荔波县| 岳西县| 德钦县| 井冈山市| 绥化市| 锦屏县| 定陶县| 丁青县| 温州市| 肇庆市| 子洲县| 芮城县| 垦利县|