资源B关闭后自动关闭资源A

问题描述 投票:0回答:1

激励示例:我有一个 HTTP 客户端,其唯一目的是生成单个

InputStream
。一旦
InputStream
关闭,HTTP 客户端也应该关闭。有没有办法将 HTTP 客户端的
close()
方法订阅到流的方法?

真正的问题是通用地这样做。我可以创建

InputStream
的子类覆盖
close()
并添加
httpClient.close()
,但也许明天我会面临同样的问题,但它不是 Http 客户端,而是文件句柄,或者我需要处置多个资源 B,当 A 关闭时 C、D,依此类推。能够将可关闭资源“订阅”到另一个资源将是理想的选择,但 API 似乎不支持这一点。

java resources autocloseable
1个回答
0
投票

我认为你可以使用侦听器或观察者模式。这种模式允许一个资源(例如,InputStream)在关闭时通知订阅的资源,从而有效地创建订阅机制。

例如

public class SubscribableCloseable implements Closeable {
    private final Closeable mainResource;
    private final List<Closeable> subscribers = new ArrayList<>();

    public SubscribableCloseable(Closeable mainResource) {
        this.mainResource = mainResource;
    }

    public void subscribe(Closeable resource) {
        if (resource != null) {
            subscribers.add(resource);
        }
    }

    @Override
    public void close() throws IOException {
        IOException exception = null;

        try {
            // Close the main resource first
            mainResource.close();
        } catch (IOException e) {
            exception = e; // Capture any exception from the main resource close
        } finally {
            // Close all subscribed resources
            for (Closeable subscriber : subscribers) {
                try {
                    subscriber.close();
                } catch (IOException e) {
                    if (exception == null) {
                        exception = e; // Capture the first exception encountered
                    } else {
                        e.printStackTrace(); // Log subsequent exceptions
                    }
                }
            }
        }

        // If any exception occurred during closing, throw the first one encountered
        if (exception != null) {
            throw exception;
        }
    }
}

现在您可以将多个可关闭资源订阅到一个主可关闭资源,例如 InputStream。

public class HttpClientExample {
    public static void main(String[] args) throws IOException {
        URL url = new URL("http://example.com");
        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
        InputStream inputStream = connection.getInputStream();
        SubscribableCloseable subscribableStream = new SubscribableCloseable(inputStream);

        // Subscribe the HttpURLConnection to the InputStream's close event
        subscribableStream.subscribe(() -> connection.disconnect());

        // Use the InputStream as needed
        // ... (read from the stream, process data, etc.)

        // Close the SubscribableCloseable, which triggers all subscribed closeables
        subscribableStream.close();
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.