1

我有一个关于声明性 OSGi 服务的问题。我有以下界面:

  public interface PrintService {
    public void print();
  }

及其实施:

    public class PrintServiceImpl implements PrintService {

      @Override
      public void print() {
        System.out.println("Hello from PrintServiceImpl!");
      }
    }

OSGI-INF/component.xml:

<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" name="service">
   <implementation class="service.PrintServiceImpl"/>
   <service>
      <provide interface="print.PrintService"/>
   </service>
</scr:component>

清单.MF:

Service-Component: OSGI-INF/component.xml

在我安装服务并启动它之后,什么也没发生。如何激活它并将“ Hello from PrintServiceImpl! ”打印到控制台。

4

6 回答 6

3

您应该明确表示您希望服务在捆绑包启动时启动。否则,它会被懒惰地实例化,并且认为没有其他服务需要 PrintService,它根本不会被实例化。

您可以使用属性控制您的服务生命周期(关于捆绑生命周期)enabledimmediate. enabled是微不足道的:指示捆绑包启动时您的服务是否启用。immediate指示此服务是否懒惰。将立即immediate="true"启动您的服务,将应用惰性实例化(即等到其他一些服务将此服务作为依赖项请求)immediate="false"

例如

<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" name="PrintService"
activate="activate" 
deactivate="deactivate"
modified="modified"
enabled="true" 
immediate="true">

正如 Chris 提到的,如果您希望您的服务在激活时执行某些操作,您应该在activate生命周期方法中添加一些代码(请注意,可以在组件描述符中指定方法的名称,就像上面明确完成的那样)

protected final void activate() {
    print();
}
于 2012-06-14T12:27:20.533 回答
2

为什么你希望你的print方法被调用?它是服务接口的一部分,因此在您可以绑定到它并调用它的客户端之前,它不会被调用。

如果您services在控制台中键入命令,您应该会看到您的捆绑软件正在发布print.PrintService服务;这意味着您的组件正在工作。如果您没有看到这一点,那么您可能会错过 Tom Seidel 在上述评论中建议的 SCR 捆绑包之类的东西。

于 2012-06-13T11:08:28.077 回答
1

也许您想通过您的激活方法进行打印?

public class PrintServiceImpl implements PrintService {
    protected final void activate() {
        System.out.println("Hello from PrintServiceImpl!");
    }
    protected final void deactivate() {
        System.out.println("Goodbye from PrintServiceImpl!");
    }
    ...
}

否则,Neil 的答案是正确的:您需要一个通过 ServiceTracker 使用服务或<reference>显式调用 print() 方法的客户端。

于 2012-06-13T21:30:12.247 回答
1

以上所有答案都是正确的。现在要在 shell 上打印一些东西,你可以编写如下内容:

public interface PrintService {
    public void print();
}

实施:

public class PrintServiceImpl implements PrintService {

      @Override
      public void print() {
        System.out.println("Hello from PrintServiceImpl!");
      }
}

组件.xml:

<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" name="service">
   <implementation class="service.PrintServiceImpl"/>
   <service>
      <provide interface="print.PrintService"/>
   </service>
</scr:component>

现在您可以使用命令来调用您的打印方法:

public class PrintCommand implements Command {

    private PrintService printer;

    public void setPrinter(PrintService printer) {
        this.printer = printer; 
    }

    public void unsetPrinter(PrintService printer) {
        this.printer = null;
    }

    @Override
    public void execute(String line, PrintStream arg1, PrintStream arg2) {    
        printer.print();
    }

    @Override
    public String getName() {
        return "print";
    }

    @Override
    public String getShortDescription() {
        return "just a printer";
    }

    @Override
    public String getUsage() {
        return "print";
    }

}

您的 component.xml 应该有一个新条目:

<component name="PrintCommand">
    <implementation class="PrintCommand"/>
    <service>
        <provide interface="org.apache.felix.shell.Command"/>
    </service>
    <reference
        name="printer"
        interface="PrintService"
        bind="setPrinter"
        unbind="unsetPrinter"
        cardinality="1..1"
        policy="static"
    />
</component>

命令界面是 Apache Felix Shell 的一部分,如果您现在运行 Felix 并help在控制台中输入,您将看到所有已注册的命令,并且还有 PrintCommand print。如果您现在在 shell 中键入 print,您将看到文本。

于 2012-06-14T13:45:17.440 回答
0

你有没有得到这个工作?对我来说,Eclipse .ds 包还没有启动,因此该服务还没有注册(还)。当我手动启动它时,我的服务已正确注册。

于 2013-10-29T12:59:13.553 回答
0

使用注解时,会在 OSGI-INF/... 文件夹下自动生成 XML 文件。

  public interface PrintService {
    public void print();
  }

  implementation with annotations: 

  @Component(service = PrintService.class)
  public class PrintServiceImpl implements PrintService {

      @Activate
      public void activate() {
         print();
      }

      @Override
      public void print() {
        System.out.println("Hello from PrintServiceImpl!");
      }
    }

正如我之前所说,XML 文件是自动创建的。使用@Component(service = PrintService.class) 注解,我们将PrintService 注册到OSGi 框架(如ServiceTracker 中的registerService 方法)。注册服务时,将调用 Activate 方法。方法名可以是任何东西。只需在 OSGi 框架中添加@Activate 注释以说“当服务注册时,调用@Activate 注释下的方法”。

于 2020-02-28T15:12:22.977 回答