SpringBoot的reload加载器的方法

2025-05-29 0 35

背景

springboot越来越多的被大家所使用SpringBoot DevTool实现热部署

出现了相同类castException

分析

首先确定出现相同类的castException比如是由于classloader不同造成的。

一个class是否相同取决于两个因素

  1. classloader相同
  2. class文件相同

即不同classloader解释出来的class是不同的class

我们在学习jdbc的时候常见的使用

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35
/**

* 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());

}

从上面我们可以了解不同的classloader解释的相同class也无法互相转换

这样我们把目标放在devtools上。

我们在springboot中引入了如下依赖

?

1

2

3

4

5
<dependency>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-devtools</artifactId>

<optional>true</optional>

</dependency>

那么如何排除devtool的依赖呢?

在application.properties中增加

?

1
spring.devtools.restart.enabled=false

发现启动时仍然可以看出使用的restartedMain

2018-03-19 22:04:37.641 INFO 53428 — [restartedMain] s.w.s.m.m.a.RequestMappingHandlerAdapter : 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] s.w.s.m.m.a.RequestMappingHandlerAdapter : Detected ResponseBodyAdvice bean in org.springframework.boot.actuate.autoconfigure.EndpointWebMvcHypermediaManagementContextConfiguration$ActuatorEndpointLinksAdvice
2018-03-19 22:04:37.956 INFO 53428 — [restartedMain] o.s.w.s.handler.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] o.s.w.s.handler.SimpleUrlHandlerMapping

这边线程名为restartedMain 为啥设置spring.devtools.restart.enabled 无效呢?

代码

在对应devtools的包中使用了ApplicationListener

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14
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();

}

}

很明显其实restarter的开启是从系统变量中读取 而并非从spring的环境中读取 正如注释所说 其实此刻使用spring的property还太早

因此可以使用系统变量

因此我们可以使用jvm参数

SpringBoot的reload加载器的方法

?

1
-Dspring.devtools.restart.enabled=false

果然此时一切就OK了

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

那在Spring的配置文件中配置的目的是啥呢?

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57
/**

* 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 milliseconds) to wait between polling for classpath changes.

*/

private long pollInterval = DEFAULT_RESTART_POLL_INTERVAL;

/**

* Amount of quiet time (in milliseconds) 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;

}

从代码中看到似乎是用来配置是否监听能否自动重启

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70
/**

* 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;

}

}

}

整个根据该配置来返回是否注册对应的watchService

当然我们也可以移除该jar

需要注意的是 当将这一段代码注释时 需要重新

?

1
mvn clean

否则有可能无法自动排除该jar

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持快网idc。

原文链接:https://my.oschina.net/qixiaobo025/blog/1648121

收藏 (0) 打赏

感谢您的支持,我会继续努力的!

打开微信/支付宝扫一扫,即可进行扫码打赏哦,分享从这里开始,精彩与您同在
点赞 (0)

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。

快网idc优惠网 建站教程 SpringBoot的reload加载器的方法 https://www.kuaiidc.com/112386.html

相关文章

发表评论
暂无评论