问题描述
我正在编写一个库,允许人们使用插件框架(如果您熟悉的话,它是JPF)来提供某些接口的实现。插件未存储在类路径中。该框架为每个插件提供了一个ClassLoader,因此当请求接口 MyInterface的名为 MyImpl的实现时,我可以找到正确的插件,然后使用该插件的ClassLoader加载类,从中可以创建一个实例如果我对构造函数有所了解。到目前为止,一切都很好。
I am writing a library where I allow people to provide implementations of certain interfaces using a plugin framework (it's JPF if you're familiar). The plugins are not stored in the classpath. The framework gives me a ClassLoader for each plugin, so when implementation named "MyImpl" of interface "MyInterface" is requested, I can find the correct plugin, and then use that plugin's ClassLoader to load the class, from which I can make an instance if I know something about the constructor. So far so good.
但是,现在我有一种情况,我需要调用仅在该特定实现上可用的方法。因此,有两种方法可以尝试执行此操作:
However, now I have a case where I need to call a method that is only available on that particular implementation. So, there are two ways I could try to do this:
方法1:
// Makes sure that MyImpl has been loaded, using the custom classloader
Plugins.getClass(MyInterface.class, "MyImpl");
// This line will not compile because MyImpl is not available at build time
MyImpl foo = new MyImpl();
// If I could get this far, this line would work:
foo.methodOnlyInMyImpl();
方法2:
// This call will get an instance of MyImpl (already written and tested)
MyInterface foo = Plugins.getInstance(MyInterface.class, "MyImpl");
// Compiler error because there is no MyInterface.methodOnlyInMyImpl method.
foo.methodOnlyInMyImpl()
方法1是两者的清理者,因为它是最类似于如果该类为普通并且无法通过插件访问的代码编写方式。
Method 1 is the cleaner of the two, as it is most similar to how you would write the code if the class were "normal" and not accessible via a plugin. However, neither compiles.
到目前为止我已经提出的选项:
A.使用方法2,但是使用反射来做methodOnlyInMyImpl方法调用(请,不!)
B.将插件类放在构建路径中,然后使用方法1进行编译。 (我目前的最爱)。
C. B +安装插件后,将类文件复制到类路径中的另一个目录中,以便系统类加载器可以加载它们(引起其他问题)
Options I've come up with so far:
A. Use Method 2, but use reflection to do the methodOnlyInMyImpl method call (please, no!)
B. Place the plugin classes in the build path and then use Method 1, which would compile. (my current favorite)
C. B + when plugins are installed, copy the classfiles to another directory that is in the classpath, so the system classloader can load them (causes other problems)
所以,我的问题是:
- 我错过了另一个更好的主意吗?
- 如果我执行B,运行时会遇到问题吗?毕竟,使用MyImpl的类可能已经使用系统类加载器加载了。因此,一旦看到
MyImpl foo
,它将不会尝试使用系统类加载器加载MyImpl,这将失败(即使Plugins.newInstance调用将提供
- Am I missing another idea that's better?
- If I do B, will I have problems at runtime? After all, the class using MyImpl will presumably have been loaded using the system classloader. So, as soon as it sees
MyImpl foo
, won't it try to load MyImpl using the system classloader, which will fail (even though the Plugins.newInstance call would provide an instance of MyImpl)?
推荐答案
首先,从插件机制中获得什么好处?您需要针对真正的实现实施?插件应该实现一个接口,您可以通过该接口使用实现。
First, what advantage you get from the plugin mechanism, when you need to implement against the real implementation? The plugin should implement an interface and you can use the implementation via the interface.
我对JPF并不满意,但是Java类在由不同的类加载器加载时是不兼容的。但是有两种可能的方法:
I am not fimilar with JPF, but java classes are never compatible when loaded by different classloaders. But there are two possible ways:
-
接口在您的类加载器中,插件类加载器将您的类加载器作为父类,因此界面与您的界面相同。当在接口中声明该方法时,代码2应该与此一起工作。
The interface is in your classloader, the plugin classloader has your classloader as parent, so its interface is the same as yours. The code 2 should work with this, when the method is decladed in the interface.
您可以使用序列化。这是在独立的类加载器之间传输数据对象的一种更有用的有限方式。我需要使用它在两个webapp之间使用带有请求参数的跨上下文调度。
You can use serialisation. This is a limited way more usefull transfering data objects between independent classloaders. I needed to use this for cross context dispatching with request parameter between two webapps.
这篇关于如何使用通过不同的Java类加载器加载的实现?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!