使用 Maven 为 OSGi 构建基于反射的服务
Build a reflection based service for OSGi with maven
我正在考虑修改我现有的 java 框架以使用 OSGi。我有几个组件依赖于反射并使用任何类型的 class (如 bean 和持久性服务)。
我对 OSGi 还不是很有经验,但据我所知,OSGi 包只能看到它显式导入的包中的 classes。如果我使用 maven-bundle-plugin 构建一个包并指定一个通配符作为导入包,它会在构建时解析代码引用的包。我需要代码在构建时未知的包中使用 classes。
我想实现的是bundle-A可以使用bundle-B中的persistence-framework来持久化属于bundle-C的classes。虽然 bundle-B 在构建时不知道 bundle-C。
我需要哪些清单条目以及如何使用 maven-bundle-plugin 设置它们?
此外,由于不同的包可以使用多个相同的 class 版本,这在 OSGi 环境中是否有意义?如果我理解正确,Bundle-A 和 Bundle-B 可能会看到 Bundle-C 的不同版本。如果 Bundle-A 现在将位于 Bundle-C 中的 class 的对象传递给 Bundle-B,然后 Bundle-B 在 class 上使用反射,Bundle-B 会按原样看到 class在它的 Bundle-C 中定义或在 Bundle-A 的 Bundle-C 中定义。
例如,如果我在 Bundle-C 中有以下 classes:
class Y {
[...]
}
class X {
Y y;
[...]
}
Bundle-A 和 B 的 Bundle-C 不同。B 将 class X 的对象传递给 A。如果 B 现在发现字段 y 并解析它是 class 它将解析 Y因为它在它的 Bundle-C 版本或 A 已知的版本中?
简而言之,即使我有一个从所有捆绑包中导入所有 classes 的捆绑包,这对创建服务以将对象持久保存到数据库中是否有用?
您在一篇文章中有多个问题:)
要在 OSGi 环境中设置 JPA,您可以 check my blog。
OSGi 环境中的 JPA 实现以另一种方式工作。它挂钩到捆绑侦听器,如果捆绑以持久性 (@Entity) classes 启动,它将加载它们。
关于 class 版本:
通常 - 如果您希望某些服务包识别您的 classes,您可以 'inject' 使用包片段。在你的情况下 - 你有一个直接依赖(X 取决于 Y),因此任何加载 class X 的包都会加载 class Y(具有特定版本)。
在 OSGi 环境中,您可以使用不同的 class 版本,但不能混合使用。实际上,一个包依赖于特定的 class 版本(已声明或首次找到)。事实上 - 每个 class 都由其名称和 class 加载程序标识来标识。因此,强制捆绑使用来自不同 class 加载程序(版本)的相同 class 将导致 'classloader poisoning' 和许多难以追踪的异常。
玩得开心
class加载的整个问题仅在加载 class 时才相关。反射在 OSGi 中的工作方式与在 OSGi 外部的工作方式相同。
因此,如果您在 bundle b 中有一个方法将 Object 作为参数。然后,您可以使用 bundle c 中定义的 Class 实例从 bundle A 调用此方法。即使 bundle b 没有导入对象的包,它仍然可以使用反射来处理对象。
如果你想在一个不导入包的包中按名称加载 classes,安全的方法是给它 class 包含 class是的。
例如,您可以在 bundle b 中使用此方法:
public Object loadTest(ClassLoader loader, String name) {
return loader.loadClass(name);
}
现在的问题当然是如何在bundle a中得到bundle b的classloader。最简单的方法是使用 MyClass myObject = new MyClass() 从 b 创建一个 class。 Bundle a 可以在导入包时执行此操作。然后,您可以使用 myObject.getClass().getClassLoader()
获取 bundle b 的 classloader。
在 OSGi 中,每个对象的 classloader 是定义它的 bundle 的 classloader(如果你不做任何奇怪的事情)。
如果这不可能,您可以使用
获取捆绑包的 classloader
ClassLoader loader = bundle.adapt(BundleWiring.class).getClassLoader();
我正在考虑修改我现有的 java 框架以使用 OSGi。我有几个组件依赖于反射并使用任何类型的 class (如 bean 和持久性服务)。 我对 OSGi 还不是很有经验,但据我所知,OSGi 包只能看到它显式导入的包中的 classes。如果我使用 maven-bundle-plugin 构建一个包并指定一个通配符作为导入包,它会在构建时解析代码引用的包。我需要代码在构建时未知的包中使用 classes。
我想实现的是bundle-A可以使用bundle-B中的persistence-framework来持久化属于bundle-C的classes。虽然 bundle-B 在构建时不知道 bundle-C。
我需要哪些清单条目以及如何使用 maven-bundle-plugin 设置它们?
此外,由于不同的包可以使用多个相同的 class 版本,这在 OSGi 环境中是否有意义?如果我理解正确,Bundle-A 和 Bundle-B 可能会看到 Bundle-C 的不同版本。如果 Bundle-A 现在将位于 Bundle-C 中的 class 的对象传递给 Bundle-B,然后 Bundle-B 在 class 上使用反射,Bundle-B 会按原样看到 class在它的 Bundle-C 中定义或在 Bundle-A 的 Bundle-C 中定义。 例如,如果我在 Bundle-C 中有以下 classes:
class Y {
[...]
}
class X {
Y y;
[...]
}
Bundle-A 和 B 的 Bundle-C 不同。B 将 class X 的对象传递给 A。如果 B 现在发现字段 y 并解析它是 class 它将解析 Y因为它在它的 Bundle-C 版本或 A 已知的版本中?
简而言之,即使我有一个从所有捆绑包中导入所有 classes 的捆绑包,这对创建服务以将对象持久保存到数据库中是否有用?
您在一篇文章中有多个问题:)
要在 OSGi 环境中设置 JPA,您可以 check my blog。
OSGi 环境中的 JPA 实现以另一种方式工作。它挂钩到捆绑侦听器,如果捆绑以持久性 (@Entity) classes 启动,它将加载它们。
关于 class 版本:
通常 - 如果您希望某些服务包识别您的 classes,您可以 'inject' 使用包片段。在你的情况下 - 你有一个直接依赖(X 取决于 Y),因此任何加载 class X 的包都会加载 class Y(具有特定版本)。
在 OSGi 环境中,您可以使用不同的 class 版本,但不能混合使用。实际上,一个包依赖于特定的 class 版本(已声明或首次找到)。事实上 - 每个 class 都由其名称和 class 加载程序标识来标识。因此,强制捆绑使用来自不同 class 加载程序(版本)的相同 class 将导致 'classloader poisoning' 和许多难以追踪的异常。
玩得开心
class加载的整个问题仅在加载 class 时才相关。反射在 OSGi 中的工作方式与在 OSGi 外部的工作方式相同。
因此,如果您在 bundle b 中有一个方法将 Object 作为参数。然后,您可以使用 bundle c 中定义的 Class 实例从 bundle A 调用此方法。即使 bundle b 没有导入对象的包,它仍然可以使用反射来处理对象。
如果你想在一个不导入包的包中按名称加载 classes,安全的方法是给它 class 包含 class是的。
例如,您可以在 bundle b 中使用此方法:
public Object loadTest(ClassLoader loader, String name) {
return loader.loadClass(name);
}
现在的问题当然是如何在bundle a中得到bundle b的classloader。最简单的方法是使用 MyClass myObject = new MyClass() 从 b 创建一个 class。 Bundle a 可以在导入包时执行此操作。然后,您可以使用 myObject.getClass().getClassLoader()
获取 bundle b 的 classloader。
在 OSGi 中,每个对象的 classloader 是定义它的 bundle 的 classloader(如果你不做任何奇怪的事情)。
如果这不可能,您可以使用
获取捆绑包的 classloaderClassLoader loader = bundle.adapt(BundleWiring.class).getClassLoader();