我有一个运行的 Karaf 实例,由于设计不当,有人决定将一个 Hibernate 实体包含到 Kar 加载的 Jar 文件中,现在,Kar 知道我在我的 karaf 运行时中需要的 objectDao,而且,Kar zip 有其类内的@entity 符号。
所以在加载 Kar 之前不会创建表,但是我需要在我的 Karaf 实例中使用 Kar 内的 objectDao 类,并且很容易出错以了解 Kar 是否尚未加载。
我如何从稍后加载的 Kar(jar 文件)中检索一个知道 objectDao 的对象实例。
我正在考虑在 Kar 文件的源代码中创建一个单例类(知道我需要的 objectDao),然后通过反射调用 getInstance() 方法来检索对象,但我在一些论坛上读到反射和单例可能容易出错和危险。
public class myHandler (){
public void saveInfo(String info){
saveInfoIntoDatabase(info);
}
private void saveInfoIntoDatabase(String info){
Object objectProvided;
/*
Solution I want to implement
~ this converts the objectProvided
~ into the object that is equal
~ to the instance created on the Kar by loading later
*/
objectProvided.saveIntoBadDesignedDao(info);
}
}
public class InfoSaver{
ObjectDao objectDao; // The instance is being provided by the bean/service/reference features of OSGI
//this means that we have to provide the object created on the OSGI blueprint
public void saveIntoBadDesignedDao(String info){
objectDao.methodThatPersistData(info);
}
}
已经有一段代码可以完成这项工作,它是来自 OSGI 的 ServiceTracker,Kar 文件依赖于 Karaf 模块的一个接口,但是,它使用了发布-订阅设计模式。 在 kar 文件上调用 objectDao 的方法是私有的,并且通过使用公共方法访问(这是可怕的)它会给出 OSGI 错误。
#找到解决办法了
显然可以使用 OSGI 框架提供的类来跟踪您的服务(对象)
https://docs.osgi.org/javadoc/r6/core/org/osgi/util/tracker/ServiceTracker.html
通过提供 bundleContext,可以从运行在 OSGI 环境中的不同服务中获取引用,例如在 karaf 中
所以在任何已部署的 .kar(一堆可部署的 .jars,但带有像 karaf 这样的运行时部署程序的元数据)中,只要您提供在这些服务中实现的接口,就可以在其中获取您的服务实例。
基本上分3个步骤:
private ServiceTracker tracker = null;
tracker = new ServiceTracker(
bundleContext,
ITheClassUWannaTrack.class.getName(),
null );
tracker.open();
Object[] objectServices = tracker.getServices();
for ( Object obj : objectServices )
{
ITheClassUWannaTrack classTracked = (ITheClassUWannaTrack) obj;
ITheClassUWannaTrack.helloWorld();
}
你蓝图中的服务可能是这样的>
<bean id="objectService"
class="com.fictioncompany.coolpackage.TheClassUWannaTrack"
init-method="init">
<property name="bundleContext" ref="blueprintBundleContext" />
</bean>
有了这个它就暴露了,所以服务跟踪器可以在部署后在.kar中实现类
#在你的.KAR
/请注意,您必须为此创建蓝图 BEAN/服务,以便服务跟踪器实际上可以获取它并稍后获取引用/
public class TheClassUWannaTrackInKar implements ITheClassUWannaTrack{
@override
public void helloWorld(){
}
}
有了这个,所有的 Hello Worlds 都将在 for 循环中执行,如果你有在公共接口中实现的 beans 并暴露在它们相应的 bundle 蓝图中,你可以调用对象“来自未来”