您现在的位置是:首页 >学无止境 >spring.expression 随笔1 parser初始化、解析过程网站首页学无止境
spring.expression 随笔1 parser初始化、解析过程
简介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 — 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)
风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。