前言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源碼解析完了
最後
本次介紹到這裏,以上內容僅供參考。