日日操夜夜添-日日操影院-日日草夜夜操-日日干干-精品一区二区三区波多野结衣-精品一区二区三区高清免费不卡

公告:魔扣目錄網(wǎng)為廣大站長提供免費收錄網(wǎng)站服務(wù),提交前請做好本站友鏈:【 網(wǎng)站目錄:http://www.ylptlb.cn 】, 免友鏈快審服務(wù)(50元/站),

點擊這里在線咨詢客服
新站提交
  • 網(wǎng)站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會員:747

一、如何手動設(shè)置注入模型

Spring的注入模型屬于beanDefifinition的一個屬性(默認(rèn)為0),可以手動設(shè)置

xml設(shè)置

<bean id="n" class="xxxx" autowire="byType"> </bean>

 

JAVA代碼設(shè)置

public class ModelBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        AbstractBeanDefinition beanDefinition = (AbstractBeanDefinition) beanFactory.getBeanDefinition("bean"); //獲取注入模型 
        //手動設(shè)置注入模型 
        beanDefinition.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_BY_TYPE);
    }
}

二、Spring的四種注入模型

public interface AutowireCapableBeanFactory extends BeanFactory {

	/**
	 * Constant that indicates no externally defined autowiring. Note that
	 * BeanFactoryAware etc and annotation-driven injection will still be Applied.
	 * @see #createBean
	 * @see #autowire
	 * @see #autowireBeanProperties
	 */
    /**
     * 默認(rèn)的裝配模式,如果注入indexBean,沒有在屬性上加@Autowired或者@Resource,這時候,indexBean是無法注入的
     */
	int AUTOWIRE_NO = 0;

	/**
	 * Constant that indicates autowiring bean properties by name
	 * (applying to all bean property setters).
	 * @see #createBean
	 * @see #autowire
	 * @see #autowireBeanProperties
	 */
    /**
     * 通過屬性名自動裝配。Spring尋找與需要自動連接的屬性同名的bean。
     * 例如,如果一個bean定義按名稱設(shè)置為自動裝配,并且它包含一個master屬性(也就是說,它有一個setMaster(…)方法),
     * Spring就會查找一個名為master的bean定義,并使用它來設(shè)置屬性。
     */
	int AUTOWIRE_BY_NAME = 1;

	/**
	 * Constant that indicates autowiring bean properties by type
	 * (applying to all bean property setters).
	 * @see #createBean
	 * @see #autowire
	 * @see #autowireBeanProperties
	 */
    /**
     * 如果容器中恰好存在該屬性類型的一個bean,則自動連接該屬性。
     * 如果存在多個,將拋出一個致命異常,這表明您不能對該bean使用byType自動裝配。
     * 如果沒有匹配的bean,則什么也不會發(fā)生(屬性沒有設(shè)置)。
     */
	int AUTOWIRE_BY_TYPE = 2;

	/**
	 * Constant that indicates autowiring the greediest constructor that
	 * can be satisfied (involves resolving the appropriate constructor).
	 * @see #createBean
	 * @see #autowire
	 */
    /**
     * 類似于byType,但適用于構(gòu)造函數(shù)參數(shù)。
     * 如果容器中沒有確切的構(gòu)造函數(shù)參數(shù)類型的bean,則會引發(fā)致命錯誤。
     */
	int AUTOWIRE_CONSTRUCTOR = 3;

	/**
	 * Constant that indicates determining an appropriate autowire strategy
	 * through introspection of the bean class.
	 * @see #createBean
	 * @see #autowire
	 * @deprecated as of Spring 3.0: If you are using mixed autowiring strategies,
	 * prefer annotation-based autowiring for clearer demarcation of autowiring needs.
	 */
    /**
     * 通過bean的內(nèi)省來選擇合適的自動裝配策略(根據(jù)英文翻譯,就是spring會選擇最適合裝備的策略)
     */
	@Deprecated
	int AUTOWIRE_AUTODETECT = 4;
  
}

三、Autowired注解注入源碼分析

注:此處只分析注入的核心流程,細(xì)節(jié)不在此展開

通過
AutowiredAnnotationBeanPostProcessor的postProcessProperties方法完成對@Autowired注解的處理和解析

Spring的注入模型

 


Spring的注入模型

 

這里最終會將所有打了Autowiring注解的字段和方法全部構(gòu)建成
InjectionMetadata.InjectedElement放入一個set集合中進(jìn)行處理

private InjectionMetadata buildAutowiringMetadata(Class<?> clazz) {
   if (!AnnotationUtils.isCandidateClass(clazz, this.autowiredAnnotationTypes)) {
      return InjectionMetadata.EMPTY;
   }

   List<InjectionMetadata.InjectedElement> elements = new ArrayList<>();
   Class<?> targetClass = clazz;

   do {
      final List<InjectionMetadata.InjectedElement> currElements = new ArrayList<>();

           /**
            * 遍歷類中的所有屬性字段
            */
      ReflectionUtils.doWithLocalFields(targetClass, field -> {
          
          // 查詢是否有 Autowired 注解
         MergedAnnotation<?> 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;
            }
            
            // 判斷注解中是否有 Required
            boolean required = determineRequiredStatus(ann);

            // 封裝成 AutowiredFieldElement 放入 currElements 集合
            currElements.add(new AutowiredFieldElement(field, required));
         }
      });

           /**
            * 遍歷類中所有方法
            */
      ReflectionUtils.doWithLocalMethods(targetClass, method -> {
         Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);
         if (!BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) {
            return;
         }
         
               // 查詢是否有 Autowired 注解
         MergedAnnotation<?> 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);
               }
            }
            
                   // 判斷注解中是否有 Required
            boolean required = determineRequiredStatus(ann);
            PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);
            
                   // 封裝成 AutowiredMethodElement 放入 currElements 集合
            currElements.add(new AutowiredMethodElement(method, required, pd));
         }
      });

      elements.addAll(0, currElements);
      targetClass = targetClass.getSuperclass();
   }
   while (targetClass != null && targetClass != Object.class);

   return InjectionMetadata.forElements(elements, clazz);
}

之后在調(diào)用
org.springframework.beans.factory.annotation.InjectionMetadata#inject方法進(jìn)行屬性填充

Spring的注入模型

 

其中
AutowiredAnnotationBeanPostProcessor類里面有3個內(nèi)部類,其中2個類為AutowiredFieldElement和AutowiredMethodElement,這2個類封裝了對打在字段上或者方法上的@Autowired注解進(jìn)行處理的邏輯;

Spring的注入模型

 

我們就根據(jù)AutowiredFieldElement字段上的@Autowired注解進(jìn)行分析,這個也是我們最常用的方式;

入口方法為inject方法,就是上面InjectionMetadata遍歷調(diào)用的inject方法;

Spring的注入模型

 


Spring的注入模型

 

org.springframework.beans.factory.support.DefaultListableBeanFactory#resolveDependency

Spring的注入模型

 

org.springframework.beans.factory.support.DefaultListableBeanFactory#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());
         try {
            return converter.convertIfNecessary(value, type, descriptor.getTypeDescriptor());
         }
         catch (UnsupportedOperationException ex) {
            // A custom TypeConverter which does not support TypeDescriptor resolution...
            return (descriptor.getField() != null ?
                  converter.convertIfNecessary(value, type, descriptor.getField()) :
                  converter.convertIfNecessary(value, type, descriptor.getMethodParameter()));
         }
      }

      /**
            * 解析當(dāng)前依賴是否支持多個bean注入,如:list、set、map類型等
            * 如果支持多個bean注入,則在內(nèi)部就完成bean的查找,不為空直接返回
            */
      Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);
      if (multipleBeans != null) {
         return multipleBeans;
      }

           /**
            * 根據(jù)類型查詢bean實例,可能會有多個,key為需要注入對象的名字
            */
      Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
      if (matchingBeans.isEmpty()) {
          // 判斷在依賴上面是否加了必須的條件,默認(rèn)為true
         if (isRequired(descriptor)) {
             // 拋出異常
            raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
         }
         // 如果非必須則返回null,不注入任何對象
         return null;
      }

      String autowiredBeanName;
      Object instanceCandidate;

      // 如果找出的實例大于1個
      if (matchingBeans.size() > 1) {

               // 通過依賴描述組件來推斷需要注入對象的名字
         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.
               // 如果找出來的實例為1個,則直接獲取出來,賦值給instanceCandidate
         Map.Entry<String, Object> entry = matchingBeans.entrySet().iterator().next();
         autowiredBeanName = entry.getKey();
         instanceCandidate = entry.getValue();
      }

      if (autowiredBeanNames != null) {
         autowiredBeanNames.add(autowiredBeanName);
      }
      // 判斷是否為Class,如果是則說明沒有實例化
      if (instanceCandidate instanceof Class) {
          // 實例化
         instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this);
      }
      // 將獲取到的實例候選賦值給result
      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);
   }
}

四、Autowired分析總結(jié)

先根據(jù)類型查找bean;如果沒有找到則報錯(默認(rèn)情況下@Autowired是一定需要注入一個bean的);如果查找到一個則用找到的這一個完成注入;如果查找到多個,先把這個多個放到map當(dāng)中,繼而根據(jù)屬性的名字從map當(dāng)中去獲取;能獲取到則使用獲取的這個;如果map當(dāng)中通過名字還是無法獲取則報錯;

@Autowired不會改變bean的注入模型(默認(rèn)情況下bean的注入模型還是0);@Autowired算是一種半自動注入;因為他只需要程序員告訴spring需要注入的屬性或者方法,而不需要程序員告訴spring需要注入的屬性或者方法他的值到底是哪個bean;@Autowired會根據(jù)自己的規(guī)則去查找這個bean,所以只能算作半自動注入;

五、Resource注解注入源碼分析

通過
CommonAnnotationBeanPostProcessor這個類的postProcessorProperties方

法來完成對@Resource注解的解析和處理

Spring的注入模型

 

后續(xù)的流程和Autowired差不多,就是掃描出來類所有加了Resource注解的屬性,封裝成對應(yīng)的
InjectionMetadata.InjectedElement

Spring的注入模型

 


Spring的注入模型

 

在封裝成ResourceElement時會讀取注解中的值進(jìn)行參數(shù)的賦值

Spring的注入模型

 

在調(diào)用ResourceElement的inject方法進(jìn)行屬性注入,但我們發(fā)現(xiàn)ResourceElement沒有inject方法,我們就可以猜想出,這個方法肯定繼承至父類

Spring的注入模型

 

我們最終在
InjectionMetadata.InjectedElement中找到了inject方法

Spring的注入模型

 

在調(diào)用子類ResourceElement的getResourceToInject方法

Spring的注入模型

 


Spring的注入模型

 

判斷Resource是否自定義了名字,如果自定義了,則不會走類型查詢并注入,而是會走else因為自定義了名字說明我們想根據(jù)名字注入對象;

如果沒有自定義會先根據(jù)名字判斷是否在單例池中存在或者在beanDefinitionMap中存在,存在則通過名字獲取,沒有則在通過類型去獲取,獲取到一個則進(jìn)行注入,沒有獲取到或者獲取到多個則拋異常;

Spring的注入模型

 


Spring的注入模型

 

六、Resource分析總結(jié)

 

@Resource在沒有配置name的情況下首先根據(jù)名字查找;

如果名字能查找到則返回這個查找到的(spring容器的原則是name唯一的,所以不存在通過名字能查找到多個的情況);

如果通過名字查找不到(需要注意的是這里的前提是沒有配置name的情況,spring覺得名字無所謂);因為對名字無要求,所以會再根據(jù)類型查找;那么走的就是@Autowired這一套;

如果配置了名字,spring覺得對名字有嚴(yán)格要求,所以只能根據(jù)你配置的名字查找;如果查找不到則報錯,找到了則用;

分享到:
標(biāo)簽:Spring
用戶無頭像

網(wǎng)友整理

注冊時間:

網(wǎng)站:5 個   小程序:0 個  文章:12 篇

  • 51998

    網(wǎng)站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會員

趕快注冊賬號,推廣您的網(wǎng)站吧!
最新入駐小程序

數(shù)獨大挑戰(zhàn)2018-06-03

數(shù)獨一種數(shù)學(xué)游戲,玩家需要根據(jù)9

答題星2018-06-03

您可以通過答題星輕松地創(chuàng)建試卷

全階人生考試2018-06-03

各種考試題,題庫,初中,高中,大學(xué)四六

運(yùn)動步數(shù)有氧達(dá)人2018-06-03

記錄運(yùn)動步數(shù),積累氧氣值。還可偷

每日養(yǎng)生app2018-06-03

每日養(yǎng)生,天天健康

體育訓(xùn)練成績評定2018-06-03

通用課目體育訓(xùn)練成績評定