一、 创建Plug-in Project工程,名为“PluginMgrCenter”,主要实现定时监控给定文件夹下jar包,对未加载的jar包进行加载
1、创建工程
2、工程结构如下图示意:
3、实现Activator类的方法,Activator类的作用,说白了就是该Bundle启动,停止会调用该类覆写的start(),stop()方法。
Activator类的start()方法中,保存osgi框架传进来的BundleContext对象,并启动一个定时任务。
代码如下:
package pluginmgrcenter; import org.osgi.framework.BundleActivator; import org.osgi.framework.BundleContext; import directwatcher.DirectWatcherTask; import directwatcher.ScheduleTimerPool; public class Activator implements BundleActivator { private static BundleContext bundleContext; public static BundleContext getBundleContext() { return bundleContext; } /* * (non-Javadoc) * * @see * org.osgi.framework.BundleActivator#start(org.osgi.framework.BundleContext * ) */ public void start(BundleContext context) throws Exception { bundleContext = context; try { DirectWatcherTask directWatcherTask = new DirectWatcherTask( bundleContext, "d:\\plugin\\"); ScheduleTimerPool.getInstance().schedule(directWatcherTask, 10000, 10000); } catch (Exception e) { e.printStackTrace(); } } /* * (non-Javadoc) * * @see * org.osgi.framework.BundleActivator#stop(org.osgi.framework.BundleContext) */ public void stop(BundleContext context) throws Exception { System.out.println("Bye World!"); } }4、ScheduleTimerPool.java类定义了一个简单的定时器。用于定时执行DirectWatcherTask.java中的jar包扫描任务。
package directwatcher; import java.util.Timer; import java.util.TimerTask; import java.util.concurrent.BlockingQueue; import java.util.concurrent.LinkedBlockingQueue; public class ScheduleTimerPool { private static ScheduleTimerPool scheduleTimerPool; static BlockingQueue<Runnable> queue = new LinkedBlockingQueue<Runnable>(); public static final ScheduleTimerPool getInstance() { if (null == scheduleTimerPool) { scheduleTimerPool = new ScheduleTimerPool(); } return scheduleTimerPool; } private static Timer timer; public void schedule(TimerTask task, long deplay, long interval) { if (null == timer) { timer = new Timer(); } timer.schedule(task, deplay, interval); } }
5、DirectWatcherTask.java中run()方法实现了对指定路径的jar包进行扫描
a、如果发现该jar未被加载,则安装启动该jar包
b、如果该jar包版本有更新,则更新该jar包
代码如下:
* */ package directwatcher; import java.io.File; import java.io.FileFilter; import java.io.FileInputStream; import java.io.InputStream; import java.util.ArrayList; import java.util.List; import java.util.Properties; import java.util.TimerTask; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; import org.osgi.framework.Bundle; import org.osgi.framework.BundleContext; import org.osgi.framework.BundleException; import org.osgi.framework.Version; /** * @author Administrator * */ public class DirectWatcherTask extends TimerTask { private BundleContext bundleContext; public String bundleFolderPath; public DirectWatcherTask(BundleContext bundleContext, String bundleFolderPath) { super(); this.bundleContext = bundleContext; this.bundleFolderPath = bundleFolderPath; System.out.println("插件目录:" + bundleFolderPath); } @Override public void run() { try { if (bundleContext == null) { System.out.println("bundleContext is null"); return; } File folderInfo = new File(bundleFolderPath); // 如果目录不存在 if (!folderInfo.exists() || !folderInfo.isDirectory()) { System.out.println("bundleFloderPath is error!"); return; } File[] files = folderInfo.listFiles(new FileFilter() { @Override public boolean accept(File pathname) { if (!pathname.isFile()) return false; return pathname.getName().toLowerCase().endsWith(".jar"); } }); List<Bundle> newBundleList = new ArrayList<Bundle>(); for (File file : files) { ZipFile zipFile = null; try { zipFile = new ZipFile(file); ZipEntry zipEntry = zipFile .getEntry("META-INF/MANIFEST.MF"); if (zipEntry == null || zipEntry.isDirectory()) continue; InputStream inputStream = zipFile.getInputStream(zipEntry); Properties prop = new Properties(); prop.load(inputStream); // 得到插件的名称和版本 String bundleName = prop.getProperty("Bundle-SymbolicName"); Version bundleVersion = Version.parseVersion(prop .getProperty("Bundle-Version")); Bundle preBundle = null; Bundle[] bundles = bundleContext.getBundles(); for (Bundle bundle : bundles) { if (bundle.getSymbolicName().equals(bundleName)) { preBundle = bundle; break; } } Bundle newBundle = null; // 如果之前没有此插件,则安装 if (preBundle == null) { System.out.println("自动安装新插件:" + bundleName + " " + bundleVersion); FileInputStream fileInputStream = new FileInputStream( file); newBundle = bundleContext.installBundle(file.getName(), fileInputStream); fileInputStream.close(); }// 否则更新 else { if (bundleVersion.compareTo(preBundle.getVersion()) > 0) { System.out.println("自动将插件:" + bundleName + " 由 " + preBundle.getVersion() + "更新到" + bundleVersion); FileInputStream fileInputStream = new FileInputStream( file); preBundle.update(fileInputStream); newBundle = preBundle; fileInputStream.close(); } } // 尝试启动插件 if (newBundle != null) { newBundleList.add(newBundle); } } catch (IllegalStateException ex) { continue; } catch (Exception ex) { ex.printStackTrace(); } finally { if (zipFile != null) { try { zipFile.close(); } catch (Exception ex) { ex.printStackTrace(); } } } } // 尝试启动所有的插件 boolean isAllBundleStartSuccess; for (int i = 0; i < newBundleList.size(); i++) { isAllBundleStartSuccess = true; for (Bundle newBundle : newBundleList) { if (newBundle.getState() != Bundle.ACTIVE && newBundle.getState() != Bundle.STARTING) { try { newBundle.start(); } catch (BundleException e) { isAllBundleStartSuccess = false; } } } if (isAllBundleStartSuccess) { break; } } // 启动尝试启动失败的插件以打印异常信息 for (Bundle newBundle : newBundleList) { if (newBundle.getState() != Bundle.ACTIVE && newBundle.getState() != Bundle.STARTING) { try { newBundle.start(); } catch (BundleException e) { e.printStackTrace(); } } } } catch (Exception e) { System.out.println("quickwebframework_web:插件自动管理线程接到线程中止命令,线程已终止!"); } } }
这样bundle管理Bundle已经成型了。
二:配置Myeclipse的“Run Configurations”
进入“Run Configurations”页面-->单击 OSGI Framework后点击“新建”图标-->选中新建的默认名称为“New_configuration”的Launch。
在“New_configuration”的Launch右侧的“Bundles”标签页,右方选择“Deselect ALL”后,在 Bundles选择框中选择“PluginMgrCenter” bundle,如下图示意:
然后在搜索栏中搜索“*osgi”进行搜索,搜索结果中选择“org.eclipse.osgi(3.5.1.R35x_v20090827)”如下:
3、创建Plug-In测试工程
1、创建工程名为“PluginAgent”的Plug-in工程,用于被Bundle管理Bundle管理,呵呵,是不是很拗口?本文的实验就是安装,启动,更新。
工程目录结构如下:
2、其中Activator.java如下,start()方法在控制台打印“hello pluginAgent!” stop()方法打印“bye pluginAgent!”
代码如下
package pluginagent; import org.osgi.framework.BundleActivator; import org.osgi.framework.BundleContext; public class Activator implements BundleActivator { /* * (non-Javadoc) * * @see * org.osgi.framework.BundleActivator#start(org.osgi.framework.BundleContext * ) */ public void start(BundleContext context) throws Exception { System.out.println("hello pluginAgent!"); } /* * (non-Javadoc) * * @see * org.osgi.framework.BundleActivator#stop(org.osgi.framework.BundleContext) */ public void stop(BundleContext context) throws Exception { System.out.println("bye pluginAgent!"); } }
3、导出“PluginAgent”工程为“PluginAgent.jar”的jar包,路径为D:\plugin
四、测试
1、以第二步骤配置的 “New_configuration” Launch 运行。
2、执行“ss”命令,查询当前只有两个Bundle运行
3、等待控制台打印出“自动安装新插件:PluginAgent 1.0.0.qualifier”,则表示系统已经检测到“D:\plugin”目录下的jar包,并识别后开始加载。
4、“Hello pluginAgent”则表示PluginAgent.jar已经加载成功。
5、再次执行“ss”命令,观察到已经有“PluginAgent_1.0.0.qualifier”Bundle安装并且启动成功,状态为ACTIVE。
测试结果图示:
相关推荐
开发者在使用Spring OSGi时,需要了解如何编写OSGi兼容的jar包,以及如何在Spring配置文件中声明和管理OSGi服务。此外,调试和测试OSGi环境下的应用程序也是一项挑战,因为它们涉及到复杂的生命周期管理和依赖关系...
7. **Bundles**:Spring应用被打包成OSGi兼容的bundle(JAR文件),它们可以被OSGi容器加载并执行。 在实际开发中,Spring OSGi使得开发者能够利用OSGi的动态性,例如,可以在运行时安装、卸载、更新和启动Spring...
然而,在OSGi环境中,我们可以为每个版本的“myself”jar包创建一个独立的bundle,每个bundle都有自己的类加载器,它们可以并存且互不影响。 为了设置OSGi环境并进行测试,你需要以下步骤: 1. **配置OSGi框架**:...
- 确保所有依赖库都已适配OSGi环境,避免使用非OSGi友好的jar包。 - 在处理动态性时,考虑服务的生命周期管理,特别是当服务更新或移除时,确保客户端能够优雅地处理。 - 注意线程安全问题,因为多个服务消费者可能...
在Eclipse OSGi框架下,每个bundle都有自己的类加载器,这使得bundle可以有自己的类空间,避免了类加载冲突。同时,OSGi的动态性体现在bundle可以在运行时被安装、启动、停止或卸载,这极大地提高了软件的可维护性和...
5. **动态依赖解析**:OSGi框架会自动处理bundle之间的依赖关系,确保在需要时加载依赖,而在不再需要时释放。这种机制使得应用能够快速适应环境变化,如添加新的bundle或更新现有bundle。 6. **版本管理**:每个...
标题中的"ant-1.6.5-osgi.jar.zip"是一个压缩文件,它包含了两个主要元素:ant-1.6.5-osgi.jar和ant.license.txt。这个压缩包是针对Apache Ant的一个版本,具体是1.6.5版本,并且与OSGi(Open Service Gateway ...
4. **版本管理**:OSGi 对包版本进行了严格管理,确保不同 bundle 中的相同包版本不会冲突,有助于避免类加载问题。 5. **生命周期管理**:OSGi 定义了 bundle 的生命周期,包括未安装、安装、解析、启动、停止、...
描述 "osgi最新jar包org.osgi.core-4.2.0" 告诉我们这是一个最新的 OSGi jar 包,其中包含了 OSGi 的核心功能。jar(Java Archive)是 Java 平台中用于打包类文件和其他资源的标准格式。因此,`org.osgi.core-4.2.0....
标题中的“Jar转换为Bundle工具”指的是将传统的Java Archive (JAR) 文件转换为OSGI Bundle的过程。OSGI(Open Service Gateway Initiative)是一种模块化系统和Java服务框架,它允许在单个Java虚拟机(JVM)上运行...
6. **依赖管理**: Bundle的元数据(MANIFEST.MF文件)中声明了其依赖关系,OSGi框架会自动解决这些依赖。 7. **安全机制**: OSGi提供了细粒度的安全模型,可以控制Bundle对资源的访问权限。 Eclipse OSGi在Eclipse...
5. **生命周期管理**:OSGi捆绑包有启动、活动、停止和未安装等状态,框架会根据需要自动管理这些状态,确保组件的正确加载和卸载。 6. **版本管理**:OSGi支持版本化的捆绑包,允许同时存在不同版本的服务,避免...
OSGI bundle提供了一种模块化的软件开发方式,使得Java应用程序可以按需加载和卸载组件。`online-1.0.0.jar`和`jxemail-1.0.0.jar`是两个示例bundle,分别实现了在线用户管理和邮件发送的功能。通过Apache Felix这样...
这些工具能够自动生成满足OSGi规范的MANIFEST.MF,并将依赖关系正确地打包进bundle。 6. **服务注册与查找**:在OSGi环境中,服务是一种共享的资源,可以通过Service Registry进行注册和查找。一个bundle可以提供...
OSGi规范使得Java程序可以被设计成一套小型的、独立的模块(称为Bundle),这些模块可以在运行时动态地加载、卸载、启动或停止。 Felix是一个遵循OSGi规范的轻量级、模块化的Service Oriented Runtime,由Apache...
4. **自动依赖管理**:Spring OSGi可以自动管理bundle之间的依赖关系,通过声明式服务(Declarative Services, DS)来声明服务和依赖,降低配置复杂性。 5. **集成其他Spring特性**:Spring OSGi支持Spring的AOP、...
OSGi的核心概念是“bundle”,即模块化的JAR文件,它们可以有自己的类路径,并能动态地安装、启动、更新和卸载。本篇文章将深入探讨如何将classpath作为bundle发布在Felix框架中。 首先,我们需要了解OSGi的bundle...
1. **OSGi**:OSGi提供了一种模块化系统,使得Java应用程序可以被划分为称为“bundle”的组件,每个组件都有自己的类加载器,这有助于减少类冲突和管理依赖关系。它还支持动态部署和更新,使得系统能够在线升级而...
5. `target`: Maven构建后生成的输出目录,包括编译后的class文件和最终的OSGi捆绑包(可能以.jar或.bundle为扩展名)。 总结一下,这个项目旨在教授如何使用Maven创建一个基本的OSGi捆绑包,以及如何在OSGi容器中...
OSGi模块实际上是一个Java存档文件(JAR),但具有特定的OSGi清单文件(Manifest)格式。清单文件包含了模块的元数据和它的依赖关系。模块层的主要职责是定义模块的生命周期,包括模块的加载、解析、启动、停止、...