如何强制 AutoClosable 警告传播到 Java 中的类调用者?

Posted

技术标签:

【中文标题】如何强制 AutoClosable 警告传播到 Java 中的类调用者?【英文标题】:How to Force AutoClosable Warning to Propagate to Caller of Class in Java? 【发布时间】:2018-05-11 01:58:36 【问题描述】:

我是 Java 的 AutoClosable 接口的新手(但不是 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

谢谢!

【问题讨论】:

阅读 javadocs 退出 try-with-resources 块时自动调用 AutoCloseable 对象的 close() 方法 避免AutoCloseable而只使用driver.quit();有什么问题? ScaryWombat:你回答了三个问题中的哪一个?我已经阅读了文档。 @JeffC我从几十个其他方法调用这个方法,每个方法将驱动程序传递给许多不同的函数..当程序员完成WebDriver时,他可能忘记关闭它..所以我想强制执行它..和我希望它在一个中心位置执行.. 如果您使用的是 JUnit 或 TestNG,您可以创建一个方法来关闭驱动程序实例并使用属性 AfterClass、AfterMethod 等对其进行标记。如果没有 AutoClosable,这应该可以满足您的需求。如果您不想这样做或不能这样做,那就是培训问题。确保每个人都知道关闭驱动程序并提供他们可以调用的单一方法。进行代码审查并将其添加到要验证的事项清单中,然后才能签入。 @JeffC 谢谢!我将研究 JUnit 和 TestNG。当有人将鼠标悬停在该功能上时,我已经发出关闭浏览器的警告。但是,我认为我可以使用AutoClosable 以某种方式强制,但显然这是不可能的.. 【参考方案1】:

这个问题我迟到了。但是,如果我们想强制客户谨慎使用资源,这是我的看法。我们可以限制资源的创建(私有构造函数+通过为jar启用属性-Djava.security.manager来禁用反射访问)并允许客户端只提供对该资源调用的方法给资源工厂。

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");
        );
    

P.S:这可能不是推荐的方式,而只是尝试这样做。

【讨论】:

【参考方案2】:

使用Try-with-resources statement:

 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 中可以使用哪种类型

【讨论】:

对不起,但这并不能回答问题。我知道尝试使用资源。请重新阅读 OP 中的 3 个特定问题。谢谢!

以上是关于如何强制 AutoClosable 警告传播到 Java 中的类调用者?的主要内容,如果未能解决你的问题,请参考以下文章

如何强制 Hibernate 在其实体之一发生更改时不将更改传播到数据库

为啥实现Autoclosable接口的类的close方法比Sql连接关闭先调用?

强制 QWidget 结束事件传播

如何强制 PyCharm 警告未声明的类型?

警告:tensorflow:sample_weight 模式被强制从 ... 到 ['...']

如何避免 as.numeric() 中的“警告消息:强制引入的 NA”[重复]