如何强制 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连接关闭先调用?