很奇怪的现象,debug之后发现spring也取到yaml文件里的值了.
但是调用appCtx.getEnvironment().getProperty(key)死活拿不到值.
于是细心观察甚至摸清了加载yaml过程
整个流程如下
进入
ConfigurableApplicationContext appCtx = SpringApplication.run(HolerApp.class, args);
ServerUtil.setAppCtx(appCtx);
String serverPort = ServerUtil.property(ServerConst.SERVER_PORT);
log.info("Holer web server started on port " + serverPort);
ServerContainer.getContainer().start();
run():1248, SpringApplication (org.springframework.boot)
public static ConfigurableApplicationContext run(Class<?> primarySource,
String... args) {
进入
return run(new Class<?>[] { primarySource }, args);
}
public ConfigurableApplicationContext run(String... args) {
StopWatch stopWatch = new StopWatch();
stopWatch.start();
ConfigurableApplicationContext context = null;
Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
configureHeadlessProperty();
SpringApplicationRunListeners listeners = getRunListeners(args);
listeners.starting();
try {
ApplicationArguments applicationArguments = new DefaultApplicationArguments(
args);
进入
ConfigurableEnvironment environment = prepareEnvironment(listeners,
applicationArguments);
configureIgnoreBeanInfo(environment);
Banner printedBanner = printBanner(environment);
private ConfigurableEnvironment prepareEnvironment(
SpringApplicationRunListeners listeners,
ApplicationArguments applicationArguments) {
// Create and configure the environment
ConfigurableEnvironment environment = getOrCreateEnvironment();
configureEnvironment(environment, applicationArguments.getSourceArgs());
进入
listeners.environmentPrepared(environment);
bindToSpringApplication(environment);
if (!this.isCustomEnvironment) {
environment = new EnvironmentConverter(getClassLoader())
.convertEnvironmentIfNecessary(environment, deduceEnvironmentClass());
}
ConfigurationPropertySources.attach(environment);
return environment;
}
environmentPrepared():54, SpringApplicationRunListeners (org.springframework.boot)
public void environmentPrepared(ConfigurableEnvironment environment) {
for (SpringApplicationRunListener listener : this.listeners) {
进入
listener.environmentPrepared(environment);
}
}
environmentPrepared():75, EventPublishingRunListener (org.springframework.boot.context.event)
@Override
public void environmentPrepared(ConfigurableEnvironment environment) {
this.initialMulticaster.multicastEvent(new ApplicationEnvironmentPreparedEvent(
this.application, this.args, environment));
}
@Override
public void multicastEvent(ApplicationEvent event) {
multicastEvent(event, resolveDefaultEventType(event));
}
@Override
public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {
ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
for (final ApplicationListener<?> listener : getApplicationListeners(event, type)) {
Executor executor = getTaskExecutor();
if (executor != null) {
executor.execute(() -> invokeListener(listener, event));
}
else {进入
invokeListener(listener, event);
}
}
}
invokeListener():165, SimpleApplicationEventMulticaster (org.springframework.context.event)
protected void invokeListener(ApplicationListener<?> listener, ApplicationEvent event) {
ErrorHandler errorHandler = getErrorHandler();
if (errorHandler != null) {
try {
doInvokeListener(listener, event);
}
catch (Throwable err) {
errorHandler.handleError(err);
}
}
else {进入
doInvokeListener(listener, event);
}
}
@SuppressWarnings({"unchecked", "rawtypes"})
private void doInvokeListener(ApplicationListener listener, ApplicationEvent event) {
try {进入
listener.onApplicationEvent(event);
}
catch (ClassCastException ex) {
String msg = ex.getMessage();
if (msg == null || matchesClassCastMessage(msg, event.getClass())) {
// Possibly a lambda-defined listener which we could not resolve the generic event type for
// -> let's suppress the exception and just log a debug message.
Log logger = LogFactory.getLog(getClass());
if (logger.isDebugEnabled()) {
logger.debug("Non-matching event type for listener: " + listener, ex);
}
}
else {
throw ex;
}
}
}
onApplicationEvent():163, ConfigFileApplicationListener (org.springframework.boot.context.config)
@Override
public void onApplicationEvent(ApplicationEvent event) {
if (event instanceof ApplicationEnvironmentPreparedEvent) {进入
onApplicationEnvironmentPreparedEvent(
(ApplicationEnvironmentPreparedEvent) event);
}
if (event instanceof ApplicationPreparedEvent) {
onApplicationPreparedEvent(event);
}
}
加载完成后的environment长这样
private void onApplicationEnvironmentPreparedEvent(
ApplicationEnvironmentPreparedEvent event) {
List<EnvironmentPostProcessor> postProcessors = loadPostProcessors();
postProcessors.add(this);
AnnotationAwareOrderComparator.sort(postProcessors);
for (EnvironmentPostProcessor postProcessor : postProcessors) {
进入postProcessor.postProcessEnvironment(event.getEnvironment(),
event.getSpringApplication());
}
}
@Override
public void postProcessEnvironment(ConfigurableEnvironment environment,
SpringApplication application) {
进入
addPropertySources(environment, application.getResourceLoader());
}
具体的调用栈如下
![](https://img.haomeiwen.com/i13402193/f1e17884041c4b36.png)
event = {ApplicationEnvironmentPreparedEvent@2281} "org.springframework.boot.context.event.ApplicationEnvironmentPreparedEvent[source=org.springframework.boot.SpringApplication@5276d6ee]"
environment = {StandardServletEnvironment@1931} "StandardServletEnvironment {activeProfiles=[], defaultProfiles=[default], propertySources=[StubPropertySource {name='servletConfigInitParams'}, StubPropertySource {name='servletContextInitParams'}, MapPropertySource {name='systemProperties'}, OriginAwareSystemEnvironmentPropertySource {name='systemEnvironment'}, RandomValuePropertySource {name='random'}, OriginTrackedMapPropertySource {name='applicationConfig: [classpath:/application.yaml]'}]}"
logger = {LogAdapter$Log4jLog@2343}
activeProfiles = {LinkedHashSet@2344} size = 0
defaultProfiles = {LinkedHashSet@2345} size = 1
propertySources = {MutablePropertySources@2346} "[StubPropertySource {name='servletConfigInitParams'}, StubPropertySource {name='servletContextInitParams'}, MapPropertySource {name='systemProperties'}, OriginAwareSystemEnvironmentPropertySource {name='systemEnvironment'}, RandomValuePropertySource {name='random'}, OriginTrackedMapPropertySource {name='applicationConfig: [classpath:/application.yaml]'}]"
propertySourceList = {CopyOnWriteArrayList@2349} size = 6
0 = {PropertySource$StubPropertySource@2351} "StubPropertySource {name='servletConfigInitParams'}"
1 = {PropertySource$StubPropertySource@2352} "StubPropertySource {name='servletContextInitParams'}"
2 = {MapPropertySource@2353} "MapPropertySource {name='systemProperties'}"
3 = {SystemEnvironmentPropertySourceEnvironmentPostProcessor$OriginAwareSystemEnvironmentPropertySource@2354} "OriginAwareSystemEnvironmentPropertySource {name='systemEnvironment'}"
4 = {RandomValuePropertySource@2355} "RandomValuePropertySource {name='random'}"
5 = {OriginTrackedMapPropertySource@3458} "OriginTrackedMapPropertySource {name='applicationConfig: [classpath:/application.yaml]'}"
logger = {LogAdapter$Log4jLog@3469}
name = "applicationConfig: [classpath:/application.yaml]"
source = {LinkedHashMap@3471} size = 26
0 = {LinkedHashMap$Entry@3475} "server.port" -> "8080"
1 = {LinkedHashMap$Entry@3476} "server.use-forward-headers" -> "true"
2 = {LinkedHashMap$Entry@3477} "server.servlet.session.timeout" -> "86400s"
3 = {LinkedHashMap$Entry@3478} "spring.datasource.username" -> "root"
4 = {LinkedHashMap$Entry@3479} "spring.datasource.password" -> "123456"
5 = {LinkedHashMap$Entry@3480} "spring.datasource.driver-class-name" -> "com.mysql.cj.jdbc.Driver"
6 = {LinkedHashMap$Entry@3481} "spring.datasource.url" -> "jdbc:mysql://localhost:3306/holer?createDatabaseIfNotExist=true&characterEncoding=utf8&useSSL=false&serverTimezone=UTC"
7 = {LinkedHashMap$Entry@3482} "spring.datasource.platform" -> "mysql"
8 = {LinkedHashMap$Entry@3483} "spring.datasource.data" -> "classpath:conf/holer-data.sql"
propertyResolver = {PropertySourcesPropertyResolver@2347}
args = {String[0]@1295}
timestamp = 1576159995118
source = {SpringApplication@1293}
这个时候我回到我的app
ConfigurableApplicationContext appCtx = SpringApplication.run(HolerApp.class, args);
发现这里的appCtx尽然是个空对象 null
所以我觉得
public static void setAppCtx(ApplicationContext appCtx) {
appCtx = appCtx;
}
是不是被jvm理解错了
重命名为
public static void setAppCtx(ApplicationContext appCtx1) {
appCtx = appCtx1;
}
改成这样就ok了
网友评论