Java 如何在将jar文件安装到OSGi容器后调用Bundle中的一个方法
我最近开始研究OSGi框架。我有一个bundle-A。我想从我的主应用程序调用bundle-ajar中的一个方法 我已经从主应用程序加载并安装了Bundle-A。下面是我安装Bundle-A的主要应用程序的代码Java 如何在将jar文件安装到OSGi容器后调用Bundle中的一个方法,java,maven,osgi,osgi-bundle,Java,Maven,Osgi,Osgi Bundle,我最近开始研究OSGi框架。我有一个bundle-A。我想从我的主应用程序调用bundle-ajar中的一个方法 我已经从主应用程序加载并安装了Bundle-A。下面是我安装Bundle-A的主要应用程序的代码 private void initializeModelFramework() { try { FileUtils.deleteDirectory(new File("felix-cache")); FrameworkFactory frame
private void initializeModelFramework() {
try {
FileUtils.deleteDirectory(new File("felix-cache"));
FrameworkFactory frameworkFactory = ServiceLoader.load(FrameworkFactory.class).iterator().next();
Framework framework = frameworkFactory.newFramework(new HashMap<String, String>());
framework.start();
BundleContext bundleContext = framework.getBundleContext();
modulesNameVersionHolder.put("Bundle-A", "1.0.0");
List<Bundle> installedBundles = new LinkedList<Bundle>();
String basePath = "C:\\ClientTool\\LocalStorage";
for (Map.Entry<String, String> entry : modulesNameVersionHolder.entrySet()) {
String version = entry.getValue();
final String filename = name + Constants.DASH + version + Constants.DOTJAR;
final String localFilename = GoldenModulesConstants.FILE_PROTOCOL + basePath+ File.separatorChar + filename;
installedBundles.add(bundleContext.installBundle(localFilename));
}
for (Bundle bundle : installedBundles) {
bundle.start();// this will start bundle A
}
// After starting the Bundle-A, now I need to call one of the methods in Bundle-A
for(int i=0; i<=10; i++) {
//call processingEvents method of Bundle-A class GoldenModelFramework
}
} catch (Exception e) {
e.printStackTrace();
}
public class Activator implements BundleActivator {
private static final String BUNDLE_VERSION_KEY = "Bundle-Version";
private static Logger s_logger = Logger.getLogger(Activator.class.getName());
@Override
public void start(BundleContext context) throws Exception {
final Bundle bundle = context.getBundle();
final String bundleName = bundle.getSymbolicName();
final String bundleVersion = (String) bundle.getHeaders().get(BUNDLE_VERSION_KEY);
System.out.println(bundleName+" - "+bundleVersion);
}
@Override
public void stop(BundleContext context) throws Exception {
System.out.println("Bye.!");
}
}
下面是我在Bundle-A-jar中的类。一旦Bundle-A启动,我需要从上面的主应用程序代码调用processingEvents
方法
public class GoldenModelFramework {
private static final Logger LOGGER = Logger.getLogger(GoldenModelFramework.class.getName());
private static final long checkingAfterEveryXMinutes = 15L;
public GoldenModelFramework() {
// following the traditions
}
public static void processingEvents(final String item) {
for (BundleRegistration.HolderEntry entry : BundleRegistration.getInstance()) {
final String response = entry.getPlugin().process(item);
System.out.println(response);
}
}
}
我不确定什么是正确的方法?我知道一种方法是在我使用基于maven的项目时,在我的主应用程序pom.xml文件中添加这个Bundle-A的依赖项。但我不这么认为这是正确的方法。因为最终,我会有更多的捆绑包,所以应该有一些其他的方法,我不知道
我应该在这里使用ServiceListener还是ServiceTracker?基于我的代码的任何简单示例都将帮助我更好地理解。谢谢
我希望这个问题足够清楚。加载并安装Bundle-A后,我试图调用其中一个方法。您有几种选择: 动态导入包 您可以使用DynamicImport包而不是导入包。在这种情况下,主捆绑启动时,捆绑-A不必处于活动状态。虽然这是可行的,但我不推荐这种解决方案,因为我不喜欢DynamicImport包。当然,在这种情况下,bundle A必须是主bundle的依赖项 使用反射 您可以使用反射调用所需的方法,如下所示(示例草稿): goldenframeworkapi将是主bundle和bundle-a的依赖项。主bundle将使用它,而bundle-a将实现它 以下是bundle A如何实现它:
public class GoldenFrameworkOSGiImpl {
public void processingEvents(final String item) {
GoldenModelFramework.processEvents(item);
}
}
在bundle-A中创建一个Activator类(我将省略该Activator中的代码以减少键入):
正如你所知道的Bundle-A的代码一样,你可以作弊一点。当bundle-A处于活动状态时,您可以确保您需要的服务已注册。但是,将来您应该考虑基于事件的工作(例如使用ServiceTracker)。我的意思是这将是一个糟糕的做法:):
这可能会暂时解决您的问题,您可以继续工作。但是,请考虑阅读一本书,比如“OSGi在行动中”,对OSGi捆绑和服务生命周期有一种感觉,这样你就可以重新设计你的框架了。你能在第三个例子的基础上给我一个简单的例子吗?通过这种方式,我将更容易理解并相应地编写代码。我对OSGi框架一无所知。谢谢你的帮助。用一个例子编辑了我的答案。请注意,我对你的问题和答案有一种奇怪的感觉。我展示了一些技巧,但是如果你更深入地研究OSGi世界,你可能会以一种甚至不需要这样技巧的方式设计代码。谢谢Balazs的建议。你能告诉我你对我的问题有什么疑问吗?通过这种方式,我可以想到我在设计中犯了什么错误,我还能做些什么来改进它。这是我的一种感觉。也许如果我看到背后的动机,我就会知道为什么我会有这种感觉。如果你不介意的话,我想说几件事。我不知道BundleRegistration类的用途是什么,但是用一个名为getInstance()的函数返回集合对我来说有些奇怪。另外,我猜GoldenFramework类有更多的方法,因为在本例中,它将是一个简单的Util类,通常有一个私有构造函数(因为Util类是不可实例化的)。但正如我所说的:框架背后的动机将是有趣的部分。从一个更方便的层次开始可能会更好,你现在正在尝试在爬行之前跑步。最简单的入门方法是使用bndtools。这是一个很好的起点:
public interface GoldenModelFrameworkOSGi {
void processingEvents(final String item);
}
public class GoldenFrameworkOSGiImpl {
public void processingEvents(final String item) {
GoldenModelFramework.processEvents(item);
}
}
public class Activator {
private ServiceRegistration goldenFrameworkSR;
@Override
public void start(BundleContext context) {
goldenFrameworkSR = context.registerService(GoldenFrameworkOSGi.class, new GoldenFrameworkOSGi(), new HashTable());
}
@Override
public void stop(BundleContext context) {
goldenFrameworkSR.unregister();
}
}
ServiceReference sr = context.getServiceReference(GoldenServiceOSGi.class);
GoldenServiceOSGi gs = context.getService(sr);
gs.processEvents(...);
context.ungetService(sr);