注意:就我而言,如果这很重要,我正在使用Apache Felix
实现。
我已经编写了捆绑包,我将其用作测试。这是一个非常简单的"Hello World"捆绑包,只需在启动/停止时向stdout
打印消息:
public class Activator implements BundleActivator {
@Override
public void start(BundleContext context) throws Exception {
System.out.println("Hello, World.");
}
@Override
public void stop(BundleContext context) throws Exception {
System.out.println("Goodbye, World.");
}
}
还有MANIFEST
文件,发布起来毫无意义,因为当我通过控制台从标准发行版(可以在此处下载)部署上述捆绑包时Apache Felix
捆绑包会启动并打印出消息。
我尝试做的下一步是使用编程方法部署相同的捆绑包。不幸的是,这对我不起作用。我的代码如下所示:
public static void main(String[] args) throws Exception {
FrameworkFactory frameworkFactory = getFrameworkFactory();
Framework framework = frameworkFactory.newFramework(null);
System.out.println("BundleID = " + framework.getBundleId());
System.out.println("State = " + getState(framework.getState()));
framework.init();
System.out.println("BundleID = " + framework.getBundleId());
System.out.println("State = " + getState(framework.getState()));
BundleContext bundleContext = framework.getBundleContext();
bundleContext.addBundleListener((event) -> {
System.out.println("Bundle Changed Event");
});
bundleContext.addFrameworkListener((event) -> {
System.out.println("Framework Event");
});
bundleContext.addServiceListener((event) -> {
System.out.println("Service Changed Event");
});
Bundle bundle = bundleContext.installBundle("file://<absolute-path-to-bundle-jar-same-as-above");
System.out.println("BundleID = " + bundle.getBundleId());
System.out.println("State = " + getState(bundle.getState()));
bundle.start();
System.out.println("BundleID = " + bundle.getBundleId());
System.out.println("State = " + getState(bundle.getState()));
}
private static FrameworkFactory getFrameworkFactory() throws IllegalStateException {
ServiceLoader<FrameworkFactory> loader = ServiceLoader.load(FrameworkFactory.class);
FrameworkFactory factory = null;
for (FrameworkFactory iterator : loader) {
if (factory != null) {
throw new IllegalStateException("Ambiguous SPI implementations.");
}
factory = iterator;
}
return factory;
}
private static String getState(int state) {
switch (state) {
case Bundle.UNINSTALLED:
return "UNINSTALLED";
case Bundle.INSTALLED:
return "INSTALLED";
case Bundle.RESOLVED:
return "RESOLVED";
case Bundle.STARTING:
return "STARTING";
case Bundle.STOPPING:
return "STOPPING";
case Bundle.ACTIVE:
return "ACTIVE";
default:
throw new IllegalStateException("Unknown state");
}
}
输出如下所示:
BundleID = 0
State = INSTALLED
BundleID = 0
State = STARTING
Bundle Changed Event
BundleID = 1
State = INSTALLED
BundleID = 1
State = INSTALLED
因此,据我了解,捆绑包已安装,但最后 4 行表明bundle.start()
由于某种原因被忽略了。
你能指出我缺少什么来完成这项工作吗?
经过一小时的调试和更仔细地阅读javadoc
,这种情况正在发生,因为框架只是初始化而不是启动。要制作示例工作,您只需在framework.init()
后添加framework.start()
(或者只是调用framwork.start()
,如果发现有必要,它会调用framework.init()
)。
我留下这些信息是因为有一些令人困惑的事情:
Apache Felix
官方文档包含有关将框架嵌入主机应用程序的信息。不幸的是,只有示例使用Apache Felix
自定义机制,使其无法移植到其他实现。令人困惑的是警告说明,如果要创建便携式解决方案,则应使用init()
和getBundleContext()
。下面引用的整个注释:
警告
felix.systembundle.activators
配置属性特定于 Felix 框架实现。如果希望代码与其他框架实现一起使用,则应在框架实例上调用init()
并直接使用getBundleContext()
。否则,方法将非常相似。
- JavaDoc 对于无参数版本的
init()
方法没有提到初始化与启动框架不同,尽管init(FrameworkListener...)
有这样的信息。
在调用 start 之前,此框架实际上不会启动。