Spring Developer Tools 源码分析:二、类路径监控
  TEZNKK3IfmPf 2024年03月22日 128 0

在 ​​Spring Developer Tools 源码分析:一、文件目录监控设计​​ 介绍了 devtools 提供的文件监控实现,在第二部分中,我们将会使用第一部分提供的目录监控功能,实现对开发环境中 classpath 的监控。

首先看一些这一部分可能涉及到的类图:

Spring Developer Tools 源码分析:二、类路径监控

在图中,红色斜线左上部分是第一部分中介绍的文件目录监控的类,其中 ​​FileSystemWatcher​​​ 会通过独立线程监控指定的目录,当目录内容发生变化时,通过对比快照可以获得所有监控目录变化的文件 ​​ChangedFiles​​​,然后将变化通知给实现了 ​​FileChangeListener​​ 监听的订阅者。

下面按照局部到整体的顺序介绍主要的类。

2.1 ClassPathFolders 类目录

这个类实现了 ​​Iterable<File>​​​ 接口,构造方法的参数为 ​​URL[]​​​,也就是类路径的 URL 形式。ClassPathFolders 就是简单的把 URL 转换为了 ​​List<File>​​​ 集合,最后通过 ​​iterator​​ 返回迭代器。

2.2 ClassPathRestartStrategy 重启策略

@FunctionalInterface
public interface ClassPathRestartStrategy

/**
* Return true if a full restart is required.
* @param file the changed file
* @return
boolean

接口方法根据变化的文件来决定是否需要重启。

默认提供了 ​​PatternClassPathRestartStrategy​​ 实现,这个实现支持 Ant 风格的模式匹配,通过设置 ​​excludePatterns​​​ 类设置不需要重启的文件名(从类路径开始的相对路径)。不在排除范围内的文件发生变化时,就会返回 ​​true​​ 来引起后续的重启。

2.3 ClassPathChangedEvent 类路径变化事件

该类继承了 ​​ApplicationEvent​​​,事件中包含变化的文件集合以及系统是否需要重启的标志。该类在后面的 ​​ClassPathFileChangeListener​​​ 中,会将监控目录发生变化的消息转换为 Spring 的事件,转换后就可以方便的通过 ​​@EventListener​​ 注解进一步解耦事件监听。

2.4 ClassPathFileChangeListener 类路径变化监听器

这个类实现了 ​​FileChangeListener​​​,并且会在后面的 ​​ClassPathFileSystemWatcher​​​ 中添加到 ​​FileSystemWatcher​​ 的订阅列表中。

当文件变化时,就会触发下面的方法:

@Override
public void onChange(Set<ChangedFiles> changeSet) {
boolean restart = isRestartRequired(changeSet);
publishEvent(new ClassPathChangedEvent(this, changeSet, restart));
}

这里先使用前面提到过的重启策略判断此次变化是否需要重启,然后创建一个 ​​ClassPathChangedEvent​​​ 事件,通过 Spring 的 ​​ApplicationEventPublisher​​​ 发布出去。发布事件后,所有监听 ​​ClassPathChangedEvent​​ 事件的监听器都会触发执行,在后续博客中会通过对该事件的监听和这里建立联系。

2.4 ClassPathFileSystemWatcher 类路径文件监控

类路径监控的实现类为 ​​ClassPathFileSystemWatcher​​,先看这个类的构造方法:

/**
* Create a new {@link ClassPathFileSystemWatcher} instance.
* @param fileSystemWatcherFactory a factory to create the underlying
* {@link FileSystemWatcher} used to monitor the local file system
* @param restartStrategy the classpath restart strategy
* @param
public ClassPathFileSystemWatcher(FileSystemWatcherFactory fileSystemWatcherFactory,
ClassPathRestartStrategy restartStrategy, URL[] urls) {
Assert.notNull(fileSystemWatcherFactory,
"FileSystemWatcherFactory must not be null");
Assert.notNull(urls, "Urls must not be null");
this.fileSystemWatcher = fileSystemWatcherFactory.getFileSystemWatcher();
this.restartStrategy = restartStrategy;
this.fileSystemWatcher.addSourceFolders(new

创建该类时,需要提供 FileSystemWatcher 的工厂类,​​PatternClassPathRestartStrategy​​​ 重启策略类以及要监控的类路径 ​​URL[]​​。

在构造方法中,通过工厂类获取了 ​​fileSystemWatcher​​​,设置了当前的重启策略,然后通过 ​​ClassPathFolders​​​ 包装了 ​​URL[]​​​ 数组。然后设置 ​​fileSystemWatcher​​​ 监控这些目录(​​fileSystemWatcher​​​ 通过 ​​Iterator​​​ 接口和 ​​ClassPathFolders​​ 解耦)。

​ClassPathFileSystemWatcher​​​ 还实现了 ​​InitializingBean​​​ 接口和 ​​ApplicationContextAware​​​ 接口,其中 ​​setApplicationContext​​​ 方法会在 ​​afterPropertiesSet​​ 方法前执行,两个方法的实现如下:

@Override
public void setApplicationContext(ApplicationContext applicationContext)
throws BeansException {
this.applicationContext = applicationContext;
}

@Override
public void afterPropertiesSet() throws Exception {
if (this.restartStrategy != null) {
FileSystemWatcher watcherToStop = null;
if (this.stopWatcherOnRestart) {
watcherToStop = this.fileSystemWatcher;
}
this.fileSystemWatcher.addListener(new ClassPathFileChangeListener(
this.applicationContext, this.restartStrategy, watcherToStop));
}
this.fileSystemWatcher.start();
}

虽然这里会判断 ​​restartStrategy​​​,但是 devtools 默认配置时是提供该策略的,不管你是否配置了排除目录,都会提供这个策略,只有提供了这个策略,才会有 ​​ClassPathFileChangeListener​​​,后续监听 ​​ClassPathChangedEvent​​​ 事件才能起作用。在所有Bean属性设置好后(​​afterPropertiesSet​​​),​​this.fileSystemWatcher.start()​​ 就启动了 。

此时类路径已经被监控了,后续我们需要知道 ​​ClassPathFileSystemWatcher​​​ 是何时创建的,​​ClassPathChangedEvent​​ 在何处监听的,当发生变化后,后续要怎样继续执行。

未完待续…

【版权声明】本文内容来自摩杜云社区用户原创、第三方投稿、转载,内容版权归原作者所有。本网站的目的在于传递更多信息,不拥有版权,亦不承担相应法律责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@moduyun.com

  1. 分享:
最后一次编辑于 2024年03月22日 0

暂无评论

推荐阅读
  TEZNKK3IfmPf   2024年05月17日   46   0   0 JSpspring
TEZNKK3IfmPf