Allow Devtools to be enabled irrespective of the launching ClassLoader
Closes gh-21424
This commit is contained in:
parent
30bc0ad96a
commit
6df10842d2
|
|
@ -43,14 +43,38 @@ public class DefaultRestartInitializer implements RestartInitializer {
|
|||
}
|
||||
|
||||
/**
|
||||
* Returns if the thread is for a main invocation. By default checks the name of the
|
||||
* thread and the context classloader.
|
||||
* Returns if the thread is for a main invocation. By default {@link #isMain(Thread)
|
||||
* checks the name of the thread} and {@link #isDevelopmentClassLoader(ClassLoader)
|
||||
* the context classloader}.
|
||||
* @param thread the thread to check
|
||||
* @return {@code true} if the thread is a main invocation
|
||||
* @see #isMainThread
|
||||
* @see #isDevelopmentClassLoader(ClassLoader)
|
||||
*/
|
||||
protected boolean isMain(Thread thread) {
|
||||
return thread.getName().equals("main")
|
||||
&& thread.getContextClassLoader().getClass().getName().contains("AppClassLoader");
|
||||
return isMainThread(thread) && isDevelopmentClassLoader(thread.getContextClassLoader());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the given {@code thread} is considered to be the main thread.
|
||||
* @param thread the thread to check
|
||||
* @return {@code true} if it's the main thread, otherwise {@code false}
|
||||
* @since 2.4.0
|
||||
*/
|
||||
protected boolean isMainThread(Thread thread) {
|
||||
return thread.getName().equals("main");
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the given {@code classLoader} is one that is typically used during
|
||||
* development.
|
||||
* @param classLoader the ClassLoader to check
|
||||
* @return {@code true} if it's a ClassLoader typically used during development,
|
||||
* otherwise {@code false}
|
||||
* @since 2.4.0
|
||||
*/
|
||||
protected boolean isDevelopmentClassLoader(ClassLoader classLoader) {
|
||||
return classLoader.getClass().getName().contains("AppClassLoader");
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
* Copyright 2012-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.
|
||||
|
|
@ -64,7 +64,24 @@ public class RestartApplicationListener implements ApplicationListener<Applicati
|
|||
// It's too early to use the Spring environment but we should still allow
|
||||
// users to disable restart using a System property.
|
||||
String enabled = System.getProperty(ENABLED_PROPERTY);
|
||||
if (enabled == null || Boolean.parseBoolean(enabled)) {
|
||||
RestartInitializer restartInitializer = null;
|
||||
if (enabled == null) {
|
||||
restartInitializer = new DefaultRestartInitializer();
|
||||
}
|
||||
else if (Boolean.parseBoolean(enabled)) {
|
||||
restartInitializer = new DefaultRestartInitializer() {
|
||||
|
||||
@Override
|
||||
protected boolean isDevelopmentClassLoader(ClassLoader classLoader) {
|
||||
return true;
|
||||
}
|
||||
|
||||
};
|
||||
logger.info(LogMessage.format(
|
||||
"Restart enabled irrespective of application packaging due to System property '%s' being set to true",
|
||||
ENABLED_PROPERTY));
|
||||
}
|
||||
if (restartInitializer != null) {
|
||||
String[] args = event.getArgs();
|
||||
DefaultRestartInitializer initializer = new DefaultRestartInitializer();
|
||||
boolean restartOnInitialize = !AgentReloader.isActive();
|
||||
|
|
|
|||
|
|
@ -88,6 +88,14 @@ class RestartApplicationListenerTests {
|
|||
assertThat(output).contains("Restart disabled due to System property");
|
||||
}
|
||||
|
||||
@Test
|
||||
void enableWithSystemProperty(CapturedOutput output) {
|
||||
System.setProperty(ENABLED_PROPERTY, "true");
|
||||
testInitialize(false);
|
||||
assertThat(Restarter.getInstance()).hasFieldOrPropertyWithValue("enabled", true);
|
||||
assertThat(output).contains("Restart enabled irrespective of application packaging due to System property");
|
||||
}
|
||||
|
||||
private void testInitialize(boolean failed) {
|
||||
Restarter.clearInstance();
|
||||
RestartApplicationListener listener = new RestartApplicationListener();
|
||||
|
|
|
|||
|
|
@ -542,7 +542,10 @@ To include devtools support, add the module dependency to your build, as shown i
|
|||
|
||||
NOTE: Developer tools are automatically disabled when running a fully packaged application.
|
||||
If your application is launched from `java -jar` or if it is started from a special classloader, then it is considered a "`production application`".
|
||||
If that does not apply to you (i.e. if you run your application from a container), consider excluding devtools or set the `-Dspring.devtools.restart.enabled=false` system property.
|
||||
You can control this behavior by using the `spring.devtools.restart.enabled` system property.
|
||||
To enable devtools, irrespective of the classloader used to launch your application, set the `-Dspring.devtools.restart.enabled=true` system property.
|
||||
This must not be done in a production environment where running devtools is a security risk.
|
||||
To disable devtools, exclude the dependency or set the `-Dspring.devtools.restart.enabled=false` system property.
|
||||
|
||||
TIP: Flagging the dependency as optional in Maven or using the `developmentOnly` configuration in Gradle (as shown above) prevents devtools from being transitively applied to other modules that use your project.
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue