当 Constructor#newInstance 抛出异常时获取实例?

发布于 2024-10-18 06:49:20 字数 382 浏览 3 评论 0原文

我正在开发一个简单的插件系统,其中第三方插件实现 Plugin 接口。扫描 JAR 目录,并使用 Constructor#newInstance 实例化实现类。

问题是,这些插件会回调插件主机的 register* 方法。这些注册使用 Plugin 实例作为句柄。我的问题是,如果构造函数决定失败并中途抛出,如何清理这些注册。

IncationTargetException 似乎没有任何内容来获取实例。 有没有办法获取抛出异常的构造函数的实例?

PS:通常强烈建议用户构造函数不要执行任何操作,但实际上人们正在以任何方式执行此操作。

I'm working on a simple plugin system, where third party plugins implement a Plugin interface. A directory of JARs is scanned, and the implementing classes are instantiated with Constructor#newInstance.

The thing is, these plugins call back into register* methods of the plugin host. These registrations use the Plugin instance as a handle. My problem is how to clean up these registrations if the constructor decides to fail and throw halfway through.

InvocationTargetException doesn't seem to have anything on it to get the instance. Is there a way to get at the instance of an exception throwing constructor?

P.S.: It's typically strongly advised to users that the constructor not do anything, but in practice people are doing it any ways.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

扛起拖把扫天下 2024-10-25 06:49:20

您实际上要问的是,当构造函数抛出异常时,是否有办法获取(部分)实例。

答案是否定的。但这并不是因为实例“死了”。事实上,对实例的引用仍然可以被应用程序的其他部分访问和使用......如果它在构造函数完成之前已“发布”。

真正的原因是,创建或抛出异常都不会记录与执行创建/抛出异常的方法或构造函数关联的实例。


您需要通过其他方式解决这个问题。我的建议是你制定一个规则,这些插件类必须只将实例注册为构造函数的最后一条语句;即当不再可以抛出与初始化相关的异常时。

What you are in effect asking is whether there is a way to get hold of the (partial) instance when a constructor throws an exception.

The answer is No. But it is not because the instance is "dead". In fact the reference to the instance could still be reachable and usable by other parts of the application ... if it has been "published" before the constructor completed.

The real reason is that neither creating or throwing an exception records the instance associated with the method or constructor doing the creating / throwing.


You will need to solve this some other way. My suggestion is you make it a rule that these plugin classes must only register the instance as the last statement of the constructor; i.e. when no more initialization-related exceptions could be thrown.

水晶透心 2024-10-25 06:49:20

是否可以通过持有者对象进行注册,然后在插件类成功构造后将其用于实际的插件注册?我正在考虑这样的事情:

public class MyPlugin extends BasePlugin {
    public MyPlugin(PluginRegistry registry) {
        super(registry);
        // here be things which may cause an exception
        // to be thrown, among other things
    }
}

public interface PluginRegistry {
    // method(s) for registration
}
public class PluginRegistryHolder implements PluginRegistry {
    // implementations of the required method(s) for registration
    // also a method for getting temporary registration data from within the class
}

// Actual usage in your code
public void registerPlugin(final String className) {
    PluginRegistryHolder h = new PluginRegistryHolder();
    Constructor c = /* acquire correct constructor, omitted for clarity */
    try {
        Object o = c.newInstance(new Object[] {h});
        this.actualRegistry.register(o, h.getRegistrationData());
    } catch (Throwable t) { /* die */
    }
}

所以基本上要优雅地处理注册,不要让插件类直接注册,而是通过托管代理注册。

Is it possible to do the registration through a holder object which is then used for actual plugin registration after the plugin class has been constructed successfully? I'm thinking of something like this:

public class MyPlugin extends BasePlugin {
    public MyPlugin(PluginRegistry registry) {
        super(registry);
        // here be things which may cause an exception
        // to be thrown, among other things
    }
}

public interface PluginRegistry {
    // method(s) for registration
}
public class PluginRegistryHolder implements PluginRegistry {
    // implementations of the required method(s) for registration
    // also a method for getting temporary registration data from within the class
}

// Actual usage in your code
public void registerPlugin(final String className) {
    PluginRegistryHolder h = new PluginRegistryHolder();
    Constructor c = /* acquire correct constructor, omitted for clarity */
    try {
        Object o = c.newInstance(new Object[] {h});
        this.actualRegistry.register(o, h.getRegistrationData());
    } catch (Throwable t) { /* die */
    }
}

So basically handle the registration gracefully and never let the plugin class register directly but instead through a managed proxy.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文