【发布时间】:2018-11-21 16:48:13
【问题描述】:
在我的 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 进行日志记录。
但是,这似乎并不那么容易。我们第一次尝试使用更新后的日志接口,您首先构建一个记录器实例,然后通过该接口进行记录,这会导致 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() 中初始化记录器实例,而是由框架设置它。 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(或其他外观)代替; Pax 将以任何一种方式捕获日志条目。所以从技术上讲,它没有区别。
我认为我们的问题是没有人(PAX 和 Felix 都没有)实现过 OSGI LoggerFactory 接口......
- 是否有 OSGI LogService 实现 实现 LoggerFactory?
- 通过“隐式”通道(如导入 slf4j)而不是使用“显式”OSGI 接口登录是否有优势?
【问题讨论】:
标签: osgi