spring源碼解析@Value

前言java

本文轉自「天河聊技術」微信公衆號node

本次介紹下@Value這個註解的底層實現spring

 

正文express

本次介紹下@Value的底層實現緩存

底層是先解析這個裏面配置的表達式解析,再進行依賴注入微信

 

表達式解析ide

進入post

org.springframework.context.expression.StandardBeanExpressionResolver#evaluateui

@Override
   @Nullable
   public Object evaluate(@Nullable String value, BeanExpressionContext evalContext) throws BeansException {
      if (!StringUtils.hasLength(value)) {
         return value;
      }
      try {
//       從緩存中取關於這個值的表達式對象
         Expression expr = this.expressionCache.get(value);
         if (expr == null) {
            expr = this.expressionParser.parseExpression(value, this.beanExpressionParserContext);
            this.expressionCache.put(value, expr);
         }
         StandardEvaluationContext sec = this.evaluationCache.get(evalContext);
         if (sec == null) {
            sec = new StandardEvaluationContext();
            sec.setRootObject(evalContext);
            sec.addPropertyAccessor(new BeanExpressionContextAccessor());
            sec.addPropertyAccessor(new BeanFactoryAccessor());
            sec.addPropertyAccessor(new MapAccessor());
            sec.addPropertyAccessor(new EnvironmentAccessor());
            sec.setBeanResolver(new BeanFactoryResolver(evalContext.getBeanFactory()));
            sec.setTypeLocator(new StandardTypeLocator(evalContext.getBeanFactory().getBeanClassLoader()));
            ConversionService conversionService = evalContext.getBeanFactory().getConversionService();
            if (conversionService != null) {
               sec.setTypeConverter(new StandardTypeConverter(conversionService));
            }
            customizeEvaluationContext(sec);
            this.evaluationCache.put(evalContext, sec);
         }
         return expr.getValue(sec);
      }
      catch (Throwable ex) {
         throw new BeanExpressionException("Expression parsing failed", ex);
      }
   }
expr = this.expressionParser.parseExpression(value, this.beanExpressionParserContext);

進入this

org.springframework.expression.common.TemplateAwareExpressionParser#parseExpression(java.lang.String, org.springframework.expression.ParserContext)

@Override
   public Expression parseExpression(String expressionString, @Nullable ParserContext context) throws ParseException {
      if (context != null && context.isTemplate()) {
         return parseTemplate(expressionString, context);
      }
      else {
//       表達式解析
         return doParseExpression(expressionString, context);
      }
   }

這一行

//        表達式解析
         return doParseExpression(expressionString, context);

進入

org.springframework.expression.spel.standard.SpelExpressionParser#doParseExpression

@Override
protected SpelExpression doParseExpression(String expressionString, @Nullable ParserContext context) throws ParseException {
   return new InternalSpelExpressionParser(this.configuration).doParseExpression(expressionString, context);
}

進入

org.springframework.expression.spel.standard.InternalSpelExpressionParser#doParseExpression

@Override
protected SpelExpression doParseExpression(String expressionString, @Nullable ParserContext context)
      throws ParseException {

   try {
      this.expressionString = expressionString;
      Tokenizer tokenizer = new Tokenizer(expressionString);
      this.tokenStream = tokenizer.process();
      this.tokenStreamLength = this.tokenStream.size();
      this.tokenStreamPointer = 0;
      this.constructedNodes.clear();
      SpelNodeImpl ast = eatExpression();
      Assert.state(ast != null, "No node");
      Token t = peekToken();
      if (t != null) {
         throw new SpelParseException(t.startPos, SpelMessage.MORE_INPUT, toString(nextToken()));
      }
      Assert.isTrue(this.constructedNodes.isEmpty(), "At least one node expected");
      return new SpelExpression(expressionString, ast, this.configuration);
   }
   catch (InternalParseException ex) {
      throw ex.getCause();
   }
}

這一行

//        token解析
         this.tokenStream = tokenizer.process();

返回

org.springframework.context.expression.StandardBeanExpressionResolver#evaluate

//              設置類型轉換器
               sec.setTypeConverter(new StandardTypeConverter(conversionService));

 

依賴注入

進入

org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor#postProcessMergedBeanDefinition

@Override
   public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {、
//    找到自動注入的元數據
      InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null);
      metadata.checkConfigMembers(beanDefinition);
   }

進入

org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor#findAutowiringMetadata

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);
               }
//             構建自動准入的元數據
               metadata = buildAutowiringMetadata(clazz);
               this.injectionMetadataCache.put(cacheKey, metadata);
            }
         }
      }
      return metadata;
   }

這一行

//              構建自動准入的元數據
               metadata = buildAutowiringMetadata(clazz);

進入

org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor#buildAutowiringMetadata

private InjectionMetadata buildAutowiringMetadata(final Class<?> clazz) {
      LinkedList<InjectionMetadata.InjectedElement> elements = new LinkedList<>();
      Class<?> targetClass = clazz;

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

         ReflectionUtils.doWithLocalFields(targetClass, field -> {
//          查找依賴注入註解的屬性值
            AnnotationAttributes ann = findAutowiredAnnotation(field);
            if (ann != null) {
               if (Modifier.isStatic(field.getModifiers())) {
                  if (logger.isWarnEnabled()) {
                     logger.warn("Autowired annotation is not supported on static fields: " + field);
                  }
                  return;
               }
//             判斷required的值
               boolean required = determineRequiredStatus(ann);
               currElements.add(new AutowiredFieldElement(field, required));
            }
         });

         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.isWarnEnabled()) {
                     logger.warn("Autowired annotation is not supported on static methods: " + method);
                  }
                  return;
               }
               if (method.getParameterCount() == 0) {
                  if (logger.isWarnEnabled()) {
                     logger.warn("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);
   }

解析完的自動注入元數據會存儲到本地緩存中,bean初始化時會調用,這部分的邏輯在bean初始化、依賴注入的部分解析過了

 

到這裏,spring ioc源碼解析完了

最後

 

本次介紹到這裏,以上內容僅供參考。

相關文章
相關標籤/搜索