在 OSGi DS 服务上使用 @Reference 时组件创建失败
Component creation fails when using @Reference on OSGi DS service
我正在尝试获取在 DS 组件上调用的 bind/unbind 方法。我已将其简化为不起作用的最简单示例。
如果删除绑定方法上的@Reference,则测试成功。显然,日志语句不会被调用。否则它在 AssertNotNull 上失败。
对我做错了什么有什么建议吗?向组件添加 bind/unbind 方法的正确方法是什么?
已更新代码以显示正确的方法。
界面
public interface Foo {
public abstract String bar();
}
Class
@Component(immediate = true, enabled = true, service = Foo.class, scope = ServiceScope.SINGLETON)
public class FooImpl implements Foo {
private final static Logger logger = LoggerFactory.getLogger(FooImpl.class);
@Override
public String bar() {
return "bar";
}
@Activate
public synchronized void bind() {
logger.debug(String.format("bind called for %s", this.getClass().getName()));
}
@Deactivate
public synchronized void unbind(Foo service) {
logger.debug(String.format("unbind called for %s", this.getClass().getName()));
}
}
生成的组件定义
<?xml version="1.0" encoding="UTF-8"?>
<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.3.0" activate="bindFoo" deactivate="unbindFoo" enabled="true" immediate="true" name="com.vogelware.experiment.FooImpl">
<service scope="singleton">
<provide interface="com.vogelware.experiment.Foo"/>
</service>
<implementation class="com.vogelware.experiment.FooImpl"/>
</scr:component>
测试class
class FooTest {
@Test
void test() throws InterruptedException {
ServiceTracker<Foo, Foo> testTracker = new ServiceTracker<Foo, Foo>(Activator.getContext(), Foo.class, null);
testTracker.open();
testTracker.waitForService(500);
Foo user = testTracker.getService();
testTracker.close();
assertNotNull(user); <= fails here
}
}
您的组件正在尝试将自身用作依赖项。因此,您有一个无法解决的循环引用。在满足对 Foo 服务(@Reference)的依赖之前,您的组件无法满足(因此注册为 Foo 服务)。
我的问题的答案是在 1.3 规范中,使用@Activate 和@Deactivate。我已经修改了原始问题以在代码中显示解决方案。
查看 http://blog.vogella.com/2016/06/21/getting-started-with-osgi-declarative-services/ 了解更多详情。
我正在尝试获取在 DS 组件上调用的 bind/unbind 方法。我已将其简化为不起作用的最简单示例。
如果删除绑定方法上的@Reference,则测试成功。显然,日志语句不会被调用。否则它在 AssertNotNull 上失败。
对我做错了什么有什么建议吗?向组件添加 bind/unbind 方法的正确方法是什么?
已更新代码以显示正确的方法。
界面
public interface Foo {
public abstract String bar();
}
Class
@Component(immediate = true, enabled = true, service = Foo.class, scope = ServiceScope.SINGLETON)
public class FooImpl implements Foo {
private final static Logger logger = LoggerFactory.getLogger(FooImpl.class);
@Override
public String bar() {
return "bar";
}
@Activate
public synchronized void bind() {
logger.debug(String.format("bind called for %s", this.getClass().getName()));
}
@Deactivate
public synchronized void unbind(Foo service) {
logger.debug(String.format("unbind called for %s", this.getClass().getName()));
}
}
生成的组件定义
<?xml version="1.0" encoding="UTF-8"?>
<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.3.0" activate="bindFoo" deactivate="unbindFoo" enabled="true" immediate="true" name="com.vogelware.experiment.FooImpl">
<service scope="singleton">
<provide interface="com.vogelware.experiment.Foo"/>
</service>
<implementation class="com.vogelware.experiment.FooImpl"/>
</scr:component>
测试class
class FooTest {
@Test
void test() throws InterruptedException {
ServiceTracker<Foo, Foo> testTracker = new ServiceTracker<Foo, Foo>(Activator.getContext(), Foo.class, null);
testTracker.open();
testTracker.waitForService(500);
Foo user = testTracker.getService();
testTracker.close();
assertNotNull(user); <= fails here
}
}
您的组件正在尝试将自身用作依赖项。因此,您有一个无法解决的循环引用。在满足对 Foo 服务(@Reference)的依赖之前,您的组件无法满足(因此注册为 Foo 服务)。
我的问题的答案是在 1.3 规范中,使用@Activate 和@Deactivate。我已经修改了原始问题以在代码中显示解决方案。
查看 http://blog.vogella.com/2016/06/21/getting-started-with-osgi-declarative-services/ 了解更多详情。