Как заставить AutoClosable Предупреждение распространяться на вызывающего класса в Java?

Я новичок в интерфейсе AutoClosable Java (но не новичок в Java). Я пытаюсь заставить клиентский код, который запрашивает экземпляр WebDriver закрыть driver после того, как он заканчивает использовать его (вызывая driver.quit())

Я хочу, чтобы способ заставить любой метод, который создает экземпляр WebDriver закрыть это.

Поэтому я создал новый класс, который реализует AutoClosable:

public class WebDriverLauncher implements AutoCloseable {

WebDriver driver;

public WebDriverLauncher()
{
    driver = new FirefoxDriver();
}

public WebDriver getDriver()
{
    return driver;
}



@Override
public void close() throws Exception {
    driver.quit();

    }

}

Теперь вместо непосредственного создания экземпляра WebDriver (WebDriver driver = new FirefoxDriver()) Я создаю экземпляр этого класса и возвращаю экземпляр WebDriver такой как в следующем примере:

public WebDriver launchDriver()
{
    WebDriverLauncher webDriverLauncher = new WebDriverLauncher();

    WebDriver driver = webDriverLauncher.getDriver();

    return driver;
}

Когда я делаю это, я получаю предупреждение / ошибку: Resource leak: 'webDriverLauncher' is never closed

Поскольку я не могу закрыть ресурс в этом методе, потому что ресурс (т.е. WebDriver) используется в методе вызывающего launchDriver() закрыть driver,

Поэтому вместо этого я решил, что метод должен возвращать экземпляр WebDriverLauncher - например, в следующем примере:

public WebDriverLauncher launchDriver()
{
     WebDriverLauncher webDriverLauncher = new WebDriverLauncher();
     return webDriverLauncher;
}

Таким образом, вызывающий абонент будет иметь доступ к driver (позвонив по webDriverLauncher .getDriver()) и будьте предупреждены, чтобы закрыть ресурс (так я думал).

Однако, когда я попробовал это, предупреждающее сообщение полностью исчезло. Другими словами, я больше не вижу предупреждение о закрытии ресурса - ни в launchDriver() класс / метод, ни в классе вызывающего / клиентского (как я уже упоминал, я хочу, чтобы предупреждение появлялось, поэтому всякий, кто вызывает этот метод, получает предупреждение о закрытии ресурса)

Я пытаюсь понять следующее:

1) Почему предупреждение не распространяется до класса вызывающего (если ресурс никогда не был закрыт)?

2) Почему предупреждение исчезает, когда я возвращаюсь webDriverLauncher но не когда я вернусь driver?

3) Есть ли способ изменить код, чтобы предупреждение распространялось на вызывающего абонента? (чтобы предупредить вызывающего этого метода о закрытии ресурса)

4) Если это невозможно, что можно сделать, чтобы заставить клиента закрыться WebDriver?

Спасибо!

1 ответ

Использование оператора Try-with-resources:

 try (WebDriverLauncher webDriverLauncher = new WebDriverLauncher(){
     //Your Code Here
 }//webDriverLauncher.close() will be called after here weather throw any exception in try...catch block or not.

В других мирах AutoClosable Интерфейс является ограничением для определения, какой тип может быть использован в Try-with-resources statement

Я опаздываю на этот вопрос. Но вот мое мнение, если мы хотим заставить клиента осторожно использовать ресурсы. Мы можем ограничить создание ресурса (частный конструктор + отключить доступ к отражению, включив свойство -Djava.security.manager для jar) и разрешить клиенту только предоставлять метод, который будет вызываться на этом ресурсе для фабрики ресурсов.

public class MyResource implements AutoCloseable{
public static class ResourceFactory{
    public static void useResourceSafely(Consumer<MyResource> work) {
        try(MyResource res = new MyResource()){
        work.accept(res);
        }
        catch(Exception e)
        {
            e.printStackTrace();
            //you may even check for Suppressed exceptions
        }
    }
}

private MyResource() {
    System.out.println("Resource created");
}
public void doWork() {
    System.out.println("resource in use");
}
@Override
public void close() throws Exception {
    System.out.println("Closing myResource");
    
}   

}

Клиентский код может выглядеть так:

public static void main(String[] args) throws Exception{     
        ResourceFactory.useResourceSafely(s->{
            s.doWork();
            System.out.println("Check 1");
            s.doWork();
            System.out.println("Check 2");
        });
    }

PS: Возможно, это не рекомендуемый способ, это всего лишь попытка сделать это.

Другие вопросы по тегам