在我的OSGI努力中,我正在考虑另一个与日志记录相关的简单问题 .
我们已将日志记录包含在我们的捆绑包中并且可以正我们实际上正在使用pax-logging服务为我们做繁重的工作 .
import org.ops4j.pax.logging.PaxLoggingService;
import org.osgi.service.component.*;
@Component( immediate=true )
public class ComponentImpl implements TimeService {
@Reference
private PaxLoggingService logs;
@Activate
public void activate(ComponentContext ctx)
{
// deprecated legacy interface
logs.log(PaxLoggingService.LOG_INFO, "Activate called at " + getTime());
logs.log(PaxLoggingService.LOG_INFO, "Activated component " + ctx.getProperties().get("component.id"));
}
}
但有两件事困扰着我们 . 首先,直接使用 public void log(int level, String message)
方法已经deprecated since OSGI v1.4 . 其次,我们宁愿登录OSGI LogService .
然而,这似乎并不那么容易 . 我们首次尝试使用更新的日志记录接口,您首先构建一个 Logger 实例,然后登录,结果是Java AbstractMethodError:
@Component( immediate=true )
public class ComponentImpl implements TimeService {
@Reference
private PaxLoggingService logs;
@Activate
public void activate(ComponentContext ctx)
{
// fancy, new logging interface - throws exception
Logger logger = logs.getLogger(ComponentImpl.class);
logger.log(PaxLoggingService.LOG_INFO, "Activate called at " + getTime());
}
}
运行时异常(当我们尝试Apache Felix的LoggerService实现时也会发生这种情况)
java.lang.AbstractMethodError: org.ops4j.pax.logging.service.internal.PaxLoggingServiceImpl$1ManagedPaxLoggingService.getLogger(Ljava/lang/Class;)Lorg/osgi/service/log/Logger;
at com.foobar.baz.osgi.testservice.ComponentImpl.activate(ComponentImpl.java:31)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
...
at org.apache.felix.framework.BundleImpl.start(BundleImpl.java:998)
at aQute.launcher.Launcher.startBundles(Launcher.java:517)
at aQute.launcher.Launcher.activate(Launcher.java:423)
at aQute.launcher.Launcher.run(Launcher.java:301)
at aQute.launcher.Launcher.main(Launcher.java:147)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at aQute.launcher.pre.EmbeddedLauncher.main(EmbeddedLauncher.java:47)
理想情况下,您不希望在 activate()
中初始化 Logger 实例,但需要通过框架进行设置 . OSGI spec shows an example of this in section 112.3.12
@Component
public class MyComponent {
@Reference(service=LoggerFactory.class)
private Logger logger;
@Activate
void activate(ComponentContext context) {
logger.trace(“activating component id {}”,
context.getProperties().get(“component.id”));
}
}
不幸的是,这个例子也不起作用 . 引用没有得到解决,因此捆绑从未运行...我一直在网上搜索,但没有找到任何相关的东西 . 似乎大多数人不使用OSGI服务接口进行日志记录,而只是使用slf4j(或其他façade); Pax将以任一方式捕获日志条目 . 所以在技术上它没有任何区别 .
我认为我们的问题是没有人(PAX和Felix都没有)实现了OSGI LoggerFactory接口......
-
是否有OSGI LogService实现,它实现了LoggerFactory?
-
登录'implicit'通道(如导入slf4j)而不是使用'explicit' OSGI接口是一个优势吗?
1 回答
目前登录OSGi的最佳做法是使用slf4j作为前端 .
只需在课堂上使用它 . Pax-Logging为它提供后端,它也可以与后备后端一起使用 .
OSGi R7提供了一些改进的日志服务集成,但我认为这在平台上还没有广泛使用 .
使用@Reference进行日志记录的优点是,当您的日志记录后端尚未可用时,它可以消除启动时的计时问题 .
像上面这样的slf4j集成的优点是它甚至适用于需要在OSGi之外工作的混合 jar .