您现在的位置是:首页 >学无止境 >spring.expression 随笔1 parser初始化、解析过程网站首页学无止境

spring.expression 随笔1 parser初始化、解析过程

肯尼思布赖恩埃德蒙 2024-10-06 12:01:04
简介spring.expression 随笔1 parser初始化、解析过程

0. 农夫山泉能否不要装太满,每次开盖都会漏出

这里关注的是获取 spring bean 的过程

1. Test环境

可理解成spring.context以外的地方集成spring-expression

1.1 初始化

just手动调用StandardEvaluationContext.setBeanResolver(org.springframework.expression.BeanResolver) ,没啥好说的

1.2 解析

getBean:202, AbstractBeanFactory (org.springframework.beans.factory.support)
getBean:1109, AbstractApplicationContext (org.springframework.context.support)
resolve:51, BeanFactoryResolver (org.springframework.context.expression)
getValueInternal:55, BeanReference (org.springframework.expression.spel.ast)
getTypedValue:117, SpelNodeImpl (org.springframework.expression.spel.ast)
getValue:308, SpelExpression (org.springframework.expression.spel.standard)

t7:243, SpELTest$Type (cn.angel.project.angelmicroservicesample.spel)

简单格式化一下

beanFactory.getBean
	BeanResolver(org.springframework.expression.BeanResolver#resolve)
		evaluationContext(org.springframework.expression.EvaluationContext#getBeanResolver)
			ExpressionState(org.springframework.expression.spel.ExpressionState#getEvaluationContext)
				SpelNodeImpl(org.springframework.expression.spel.ast.BeanReference#getValueInternal)
					SpelExpression(org.springframework.expression.spel.standard.SpelExpression#getValue)

可以看到 spring.expression 提供了BeanResolver用来处理bean的解析,可惜spring.context 的Resolver是自己实现的,与其不相关

2. spring.context 中的做法

2.1 初始化

先看下调用栈,看下spring.context启动过程中,是怎么初始化内置的parser的

<init>:50, SpelExpressionParser (org.springframework.expression.spel.standard)
<init>:103, StandardBeanExpressionResolver (org.springframework.context.expression)
prepareBeanFactory:650, AbstractApplicationContext (org.springframework.context.support)
refresh:526, AbstractApplicationContext (org.springframework.context.support)

调用深度比较小,调用的时机也非常的早


源码走一个

// org.springframework.context.support.AbstractApplicationContext#refresh
@Override
public void refresh() throws BeansException, IllegalStateException {
	synchronized (this.startupShutdownMonitor) {
		// Prepare this context for refreshing.
		prepareRefresh();

		// Tell the subclass to refresh the internal bean factory.
		ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

		// step into ...
		// 为beanFactory准备SpelExpressionParser 
		// beanFactory此时实例已经被创建
		// 这里是为其初始化做准备
		// Prepare the bean factory for use in this context.
		prepareBeanFactory(beanFactory);

		try {
			// Allows post-processing of the bean factory in context subclasses.
			postProcessBeanFactory(beanFactory);

			// Invoke factory processors registered as beans in the context.
			invokeBeanFactoryPostProcessors(beanFactory);

			// Register bean processors that intercept bean creation.
			registerBeanPostProcessors(beanFactory);

			// Initialize message source for this context.
			initMessageSource();

			// Initialize event multicaster for this context.
			initApplicationEventMulticaster();

			// Initialize other special beans in specific context subclasses.
			onRefresh();

			// Check for listener beans and register them.
			registerListeners();

			// Instantiate all remaining (non-lazy-init) singletons.
			finishBeanFactoryInitialization(beanFactory);

			// Last step: publish corresponding event.
			finishRefresh();
		}

		catch (BeansException ex) {
			if (logger.isWarnEnabled()) {
				logger.warn("Exception encountered during context initialization - " +
						"cancelling refresh attempt: " + ex);
			}

			// Destroy already created singletons to avoid dangling resources.
			destroyBeans();

			// Reset 'active' flag.
			cancelRefresh(ex);

			// Propagate exception to caller.
			throw ex;
		}

		finally {
			// Reset common introspection caches in Spring's core, since we
			// might not ever need metadata for singleton beans anymore...
			resetCommonCaches();
		}
	}
}

// org.springframework.context.support.AbstractApplicationContext#prepareBeanFactory
/**
 * Configure the factory's standard context characteristics,
 * such as the context's ClassLoader and post-processors.
 * @param beanFactory the BeanFactory to configure
 */
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
	// Tell the internal bean factory to use the context's class loader etc.
	beanFactory.setBeanClassLoader(getClassLoader());
	
	// step into ...
	// 这个类并非实现 spring-expression,是spring-context模块自己搞的
	// 内部会委托1个parser
	beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
	beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));

	// Configure the bean factory with context callbacks.
	beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
	beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
	beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
	beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
	beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
	beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
	beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);

	// BeanFactory interface not registered as resolvable type in a plain factory.
	// MessageSource registered (and found for autowiring) as a bean.
	beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
	beanFactory.registerResolvableDependency(ResourceLoader.class, this);
	beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
	beanFactory.registerResolvableDependency(ApplicationContext.class, this);

	// Register early post-processor for detecting inner beans as ApplicationListeners.
	beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));

	// Detect a LoadTimeWeaver and prepare for weaving, if found.
	if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
		beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
		// Set a temporary ClassLoader for type matching.
		beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
	}

	// Register default environment beans.
	if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
		beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
	}
	if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
		beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
	}
	if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
		beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
	}
}

//  org.springframework.context.expression.StandardBeanExpressionResolver#StandardBeanExpressionResolver(java.lang.ClassLoader)
public StandardBeanExpressionResolver(@Nullable ClassLoader beanClassLoader) {
	// 接入 spring-expression 模块了
	this.expressionParser = new SpelExpressionParser(new SpelParserConfiguration(null, beanClassLoader));
}

2.2 解析过程

  • #{} 读取上下文、解释SpEL表达式
  • ${} 读取配置文件(PropertySource)

@Value的Javadoc已经给出了AutowiredAnnotationBeanPostProcessor,该BeanPostProcessor 在spring.context 的bean属性注入的过程调用parser解释SpEL表达式

/*
 * Copyright 2002-2020 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.springframework.beans.factory.annotation;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * Annotation used at the field or method/constructor parameter level
 * that indicates a default value expression for the annotated element.
 *
 * <p>Typically used for expression-driven or property-driven dependency injection.
 * Also supported for dynamic resolution of handler method arguments &mdash; for
 * example, in Spring MVC.
 *
 * <p>A common use case is to inject values using
 * <code>#{systemProperties.myProp}</code> style SpEL (Spring Expression Language)
 * expressions. Alternatively, values may be injected using
 * <code>${my.app.myProp}</code> style property placeholders.
 *
 * <p>Note that actual processing of the {@code @Value} annotation is performed
 * by a {@link org.springframework.beans.factory.config.BeanPostProcessor
 * BeanPostProcessor} which in turn means that you <em>cannot</em> use
 * {@code @Value} within
 * {@link org.springframework.beans.factory.config.BeanPostProcessor
 * BeanPostProcessor} or
 * {@link org.springframework.beans.factory.config.BeanFactoryPostProcessor BeanFactoryPostProcessor}
 * types. Please consult the javadoc for the {@link AutowiredAnnotationBeanPostProcessor}
 * class (which, by default, checks for the presence of this annotation).
 *
 * @author Juergen Hoeller
 * @since 3.0
 * @see AutowiredAnnotationBeanPostProcessor
 * @see Autowired
 * @see org.springframework.beans.factory.config.BeanExpressionResolver
 * @see org.springframework.beans.factory.support.AutowireCandidateResolver#getSuggestedValue
 */
@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Value {

	/**
	 * The actual value expression such as <code>#{systemProperties.myProp}</code>
	 * or property placeholder such as <code>${my.app.myProp}</code>.
	 */
	String value();

}

2.2.1 #{}

parseExpression:48, TemplateAwareExpressionParser (org.springframework.expression.common)

// spring-context 接入到 spring-expression 的内容
evaluate:147, StandardBeanExpressionResolver (org.springframework.context.expression)
evaluateBeanDefinitionString:1575, AbstractBeanFactory (org.springframework.beans.factory.support)
doResolveDependency:1251, DefaultListableBeanFactory (org.springframework.beans.factory.support)
resolveDependency:1227, DefaultListableBeanFactory (org.springframework.beans.factory.support)

// 如@Value.java中的javadoc所言,@Value注入的表达式、配置均是在这个BeanPostProcesser中处理的
inject:640, AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement (org.springframework.beans.factory.annotation)
inject:130, InjectionMetadata (org.springframework.beans.factory.annotation)
// 就这个东西
postProcessProperties:399, AutowiredAnnotationBeanPostProcessor (org.springframework.beans.factory.annotation)

// 初始化bean的所有属性
populateBean:1420, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)

doCreateBean:593, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
createBean:516, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
lambda$doGetBean$0:324, AbstractBeanFactory (org.springframework.beans.factory.support)
getObject:-1, 1134202713 (org.springframework.beans.factory.support.AbstractBeanFactory$$Lambda$135)
getSingleton:234, DefaultSingletonBeanRegistry (org.springframework.beans.factory.support)
doGetBean:322, AbstractBeanFactory (org.springframework.beans.factory.support)
getBean:202, AbstractBeanFactory (org.springframework.beans.factory.support)

// 执行单例bean的初始化
preInstantiateSingletons:897, DefaultListableBeanFactory (org.springframework.beans.factory.support)

// 初始化 no-lazy 的bean实例
finishBeanFactoryInitialization:879, AbstractApplicationContext (org.springframework.context.support)
refresh:551, AbstractApplicationContext (org.springframework.context.support)

2.2.2 ${}

// 最终反应到 StandardEnvironment.getProperty(key), 该被PropertySource所包装隐藏
// 属于是 spring.core.env 的内容了
// 即 配置文件的配置最终还是反应到了 Environment
getProperty:137, PropertySourcesPlaceholderConfigurer$1 (org.springframework.context.support)
getProperty:133, PropertySourcesPlaceholderConfigurer$1 (org.springframework.context.support)
getProperty:85, PropertySourcesPropertyResolver (org.springframework.core.env)
getPropertyAsRawString:74, PropertySourcesPropertyResolver (org.springframework.core.env)
resolvePlaceholder:-1, 1789110533 (org.springframework.core.env.AbstractPropertyResolver$$Lambda$268)
// 这之前还做了递归调用自身,处理 ${} 嵌套的场景
parseStringValue:151, PropertyPlaceholderHelper (org.springframework.util)
replacePlaceholders:124, PropertyPlaceholderHelper (org.springframework.util)
doResolvePlaceholders:239, AbstractPropertyResolver (org.springframework.core.env)
// 这个 PropertySourcesPropertyResolver 用于处理 ${}
resolveRequiredPlaceholders:210, AbstractPropertyResolver (org.springframework.core.env)
lambda$processProperties$0:175, PropertySourcesPlaceholderConfigurer (org.springframework.context.support)
resolveStringValue:-1, 652481263 (org.springframework.context.support.PropertySourcesPlaceholderConfigurer$$Lambda$437)
resolveEmbeddedValue:918, AbstractBeanFactory (org.springframework.beans.factory.support)

// 在这之前 ${}、#{} 的处理过程都是一样的
// 这里先处理 ${} 后处理其内部 #{}
doResolveDependency:1248, DefaultListableBeanFactory (org.springframework.beans.factory.support)
resolveDependency:1227, DefaultListableBeanFactory (org.springframework.beans.factory.support)
inject:640, AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement (org.springframework.beans.factory.annotation)
inject:130, InjectionMetadata (org.springframework.beans.factory.annotation)

// 属性注入都是在这个位置啦
postProcessProperties:399, AutowiredAnnotationBeanPostProcessor (org.springframework.beans.factory.annotation)
populateBean:1420, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
doCreateBean:593, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
createBean:516, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
lambda$doGetBean$0:324, AbstractBeanFactory (org.springframework.beans.factory.support)
getObject:-1, 45643137 (org.springframework.beans.factory.support.AbstractBeanFactory$$Lambda$397)
getSingleton:234, DefaultSingletonBeanRegistry (org.springframework.beans.factory.support)
doGetBean:322, AbstractBeanFactory (org.springframework.beans.factory.support)
getBean:202, AbstractBeanFactory (org.springframework.beans.factory.support)
preInstantiateSingletons:897, DefaultListableBeanFactory (org.springframework.beans.factory.support)
finishBeanFactoryInitialization:879, AbstractApplicationContext (org.springframework.context.support)
refresh:551, AbstractApplicationContext (org.springframework.context.support)
风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。