spring 的 WatchService

WatchService with spring

我正在尝试使用 spring 执行 "WatchService" 但它看起来不可能,因为当我在应用程序上下文时尝试 运行 此服务但加载 spring 当控制到达

时上下文停止
key = watcher.take();

由于没有加载应用程序上下文。

下面是完整代码

@Component
public class DirectoryWatchDemo {


    @PostConstruct
    public static void test(){
        try {
            WatchService watcher = FileSystems.getDefault().newWatchService();
            Path dir = Paths.get("C:/test");
            dir.register(watcher, ENTRY_CREATE);

            System.out.println("Watch Service registered for dir: " + dir.getFileName());

            while (true) {
                WatchKey key;
                try {
                    key = watcher.take();
                } catch (InterruptedException ex) {
                    return;
                }

                for (WatchEvent<?> event : key.pollEvents()) {
                    WatchEvent.Kind<?> kind = event.kind();

                    @SuppressWarnings("unchecked")
                    WatchEvent<Path> ev = (WatchEvent<Path>) event;
                    Path fileName = ev.context();

                    System.out.println(kind.name() + ": " + fileName);

                    if (kind == ENTRY_MODIFY &&
                            fileName.toString().equals("DirectoryWatchDemo.java")) {
                        System.out.println("My source file has changed!!!");
                    }
                }

                boolean valid = key.reset();
                if (!valid) {
                    break;
                }
            }

        } catch (IOException ex) {
            System.err.println(ex);
        }
    }

}

我这样做是因为不想手动执行"WatchService"

WatchService.take等待下一个手表键:"Retrieves and removes next watch key, waiting if none are yet present."

PostConstruct - 这是一个 Java 注释,相对于 Spring 注释 - "is used on a method that needs to be executed after dependency injection is done to perform any initialization. This method MUST be invoked before the class is put into service." 根据此文档,似乎 PostConstruct 必须 return 在bean 可以投入使用 ("MUST be invoked before the class is put into service").

但是你的PostConstruct方法没有return;所以 PostConstruct 不是你需要的。

您可以考虑实现 Spring InitializingBean 接口,它提供了一个回调方法 afterPropertiesSet。它应该允许您启动这种类型的服务方法。

否则,您可以查看 Apache VFS2 虚拟文件系统,其中包括一个文件夹监视器。那就是我的项目使用的;在系统启动时启动观察器非常容易;而且,它监视文件删除、更新和创建事件(与 Ca​​mel 文件监视程序不同)。

这是因为你有一个无限循环,因此 @PostConstruct 的方法调用永远不会 return。

(这对我来说很奇怪,@PostConstruct 适用于静态方法,但也许这可行)

因此解决方案是为您的观察者启动一个新线程。你可以用不同的方式做到这一点:

  • 刚刚开始一个新线程
  • @Async 添加到该方法(我不知道这是否适用于 @PostConstruct 方法)(主要缺点是,它在整个应用程序上下文初始化之前启动)
  • 滥用 @Scheduler 注释:@Scheduled(fixedDelay = Long.MAX_VALUE) -(相对于 @PostConstruct+@Async 的优势在于:它确实有效并且在完整的上下文之后开始已初始化)