background
Springboot is increasingly being used by everyone to achieve hot deployment using SpringBoot DevTool
The same class castException appears
analyze
First, determine whether the castException of the same class appears, for example, because the classloader is different.
Whether a class is the same depends on two factors
That is, the class explained by different classloaders is different class
Common use of jdbc when we learn
/** * Returns the {@code Class} object associated with the class or * interface with the given string name. Invoking this method is * equivalent to: * * <blockquote> * {@code Class.forName(className, true, currentLoader)} * </blockquote> * where {@code currentLoader} denotes the defining class loader of * the current class. * * <p> For example, the following code fragment returns the * runtime {@code Class} descriptor for the class named * {@code java.lang.Thread}: * * <blockquote> * {@code Class t = Class.forName("java.lang.Thread")} * </blockquote> * <p> * A call to {@code forName("X")} causes the class named * {@code X} to be initialized. * * @param className the fully qualified name of the desired class. * @return the {@code Class} object for the class with the * specified name. * @exception LinkageError if the linkage fails * @exception ExceptionInInitializerError if the initialization provoked * by this method fails * @exception ClassNotFoundException if the class cannot be located */public static Class<?> forName(String className) throws ClassNotFoundException { return forName0(className, true, ClassLoader.getCallerClassLoader());}From the above we can understand that the same classes explained by different classloaders cannot convert to each other.
In this way we target devtools.
We have introduced the following dependencies in springboot
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <optional>true</optional></dependency>
So how to exclude the dependencies of devtool?
Add in application.properties
spring.devtools.restart.enabled=false
I found that the restartedMain used can still be seen when starting
2018-03-19 22:04:37.641 INFO 53428 --- [restartedMain] swsmmaRequestMappingHandlerAdapter : Looking for @ControllerAdvice: org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@7443f7a3: startup date [Mon Mar 19 22:03:34 CST 2018]; root of context hierarchy
2018-03-19 22:04:37.654 INFO 53428 --- [restartedMain] swsmmaRequestMappingHandlerAdapter : Detected ResponseBodyAdvice bean in org.springframework.boot.actuate.autoconfigure.EndpointWebMvcHypermediaManagementContextConfiguration$ActuatorEndpointLinksAdvice
2018-03-19 22:04:37.956 INFO 53428 --- [restartedMain] oswshandler.SimpleUrlHandlerMapping : Mapped URL path [/swagger-ui.html] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
2018-03-19 22:04:37.956 INFO 53428 --- [restartedMain] oswshandler.SimpleUrlHandlerMapping
Why is the thread named restartedMain set spring.devtools.restart.enabled invalid?
Code
ApplicationListener is used in the package corresponding to devtools
private void onApplicationStartingEvent(ApplicationStartingEvent event) { // 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)) { String[] args = event.getArgs(); DefaultRestartInitializer initializer = new DefaultRestartInitializer(); boolean restartOnInitialize = !AgentReloader.isActive(); Restarter.initialize(args, false, initializer, restartOnInitialize); } else { Restarter.disable(); }}It is obvious that the restarter is actually read from system variables rather than from spring environment. As the comment says, it is actually too early to use spring property at this moment.
Therefore, system variables can be used
Therefore we can use jvm parameters
-Dspring.devtools.restart.enabled=false
Sure enough, everything is OK at this time
2018-03-19 22:18:12.928 INFO 66260 --- [main] com.f6car.base.Application : The following profiles are active: dev
2018-03-19 22:18:13.131 INFO 66260 --- [main] ationConfigEmbeddedWebApplicationContext : Refreshing org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@2a4354cb: startup date [Mon Mar 19 22:18:13 CST 2018]; root of context hierarchy
So what is the purpose of configuration in Spring's configuration file?
/** * Restart properties. */public static class Restart { private static final String DEFAULT_RESTART_EXCLUDES = "META-INF/maven/**," + "META-INF/resources/**,resources/**,static/**,public/**,templates/**," + "**/*Test.class,**/*Tests.class,git.properties,META-INF/build-info.properties"; private static final long DEFAULT_RESTART_POLL_INTERVAL = 1000; private static final long DEFAULT_RESTART_QUIET_PERIOD = 400; /** * Enable automatic restart. */ private boolean enabled = true; /** * Patterns that should be excluded from triggering a full restart. */ private String exclude = DEFAULT_RESTART_EXCLUDES; /** * Additional patterns that should be excluded from triggering a full restart. */ private String additionalExclude; /** * Amount of time (in million seconds) to wait between polling for classpath changes. */ private long pollInterval = DEFAULT_RESTART_POLL_INTERVAL; /** * Amount of quiet time (in million seconds) required without any classpath changes * before a restart is triggered. */ private long quietPeriod = DEFAULT_RESTART_QUIET_PERIOD; /** * Name of a specific file that when changed will trigger the restart check. If * not specified any classpath file change will trigger the restart. */ private String triggerFile; /** * Additional paths to watch for changes. */ private List<File> additionalPaths = new ArrayList<File>(); public boolean isEnabled() { return this.enabled; } public void setEnabled(boolean enabled) { this.enabled = enabled; }From the code, it seems to be used to configure whether the listening can be restarted automatically
/** * Local Restart Configuration. */ @ConditionalOnProperty(prefix = "spring.devtools.restart", name = "enabled", matchIfMissing = true) static class RestartConfiguration { @Autowired private DevToolsProperties properties; @EventListener public void onClassPathChanged(ClassPathChangedEvent event) { if (event.isRestartRequired()) { Restarter.getInstance().restart( new FileWatchingFailureHandler(fileSystemWatcherFactory())); } } @Bean @ConditionalOnMissingBean public ClassPathFileSystemWatcher classPathFileSystemWatcher() { URL[] urls = Restarter.getInstance().getInitialUrls(); ClassPathFileSystemWatcher watcher = new ClassPathFileSystemWatcher( fileSystemWatcherFactory(), classPathRestartStrategy(), urls); watcher.setStopWatcherOnRestart(true); return watcher; } @Bean @ConditionalOnMissingBean public ClassPathRestartStrategy classPathRestartStrategy() { return new PatternClassPathRestartStrategy( this.properties.getRestart().getAllExclude()); } @Bean public HateoasObjenesisCacheDisabler hateoasObjenesisCacheDisabler() { return new HateoasObjenesisCacheDisabler(); } @Bean public FileSystemWatcherFactory fileSystemWatcherFactory() { return new FileSystemWatcherFactory() { @Override public FileSystemWatcher getFileSystemWatcher() { return newFileSystemWatcher(); } }; } private FileSystemWatcher newFileSystemWatcher() { Restart restartProperties = this.properties.getRestart(); FileSystemWatcher watcher = new FileSystemWatcher(true, restartProperties.getPollInterval(), restartProperties.getQuietPeriod()); String triggerFile = restartProperties.getTriggerFile(); if (StringUtils.hasLength(triggerFile)) { watcher.setTriggerFilter(new TriggerFileFilter(triggerFile)); } List<File> additionalPaths = restartProperties.getAdditionalPaths(); for (File path : additionalPaths) { watcher.addSourceFolder(path.getAbsoluteFile()); } return watcher; } } }The entire configuration returns whether to register the corresponding watchService
Of course we can also remove the jar
It should be noted that when commenting this code, you need to re-
mvn clean
Otherwise, it may not be possible to automatically exclude the jar
The above is all the content of this article. I hope it will be helpful to everyone's learning and I hope everyone will support Wulin.com more.