apache.felix.dm包中的init()和start()方法有什么区别?

时间:2013-11-01 03:08:19

标签: java osgi apache-felix

我正在研究Opendaylight项目(由思科领导的开源SDN控制器项目),并发现该项目使用来自apache.felix.dm包的资源来动态管理equinox(OSGi框架)上的服务依赖项)在运行期间。

为了理解dm的机制,我在apache.felix.dm包下跟踪了ComponentImpl.java中的代码。我现在理解的是:

  1. 在满足所有服务依赖性后,DependencyManager将调用init()方法。
  2. start()方法将在init()方法之后但在类提供的服务在OSGi框架上注册之前调用。
  3. 用代码编写的调用机制如下(它们都位于ComponentImpl.java中):

    调用init()的方法:

    private void activateService(State state) {
        String init;
        synchronized (this) {
            init = m_callbackInit;
        }
        // service activation logic, first we initialize the service instance itself
        // meaning it is created if necessary and the bundle context is set
        initService();
        // now is the time to configure the service, meaning all required
        // dependencies will be set and any callbacks called
        configureService(state);
        // flag that our instance has been created
        m_isInstantiated = true;
        // then we invoke the init callback so the service can further initialize
        // itself
        invoke(init);
        // see if any of this caused further state changes
        calculateStateChanges();
    }
    

    调用start()的方法:

    private void bindService(State state) {
        String start;
        synchronized (this) {
            start = m_callbackStart;
        }
    
        // configure service with extra-dependencies which might have been added from init() method.
        configureServiceWithExtraDependencies(state);
        // inform the state listeners we're starting
        stateListenersStarting();
        // invoke the start callback, since we're now ready to be used
        invoke(start);
        // start tracking optional services
        startTrackingOptional(state);
        // register the service in the framework's service registry
        registerService();
        // inform the state listeners we've started
        stateListenersStarted();
    }
    

    现在我的问题是:init()和start()方法有什么区别?由于它们都是在OSGi框架上注册服务之前调用的,为什么需要将它们分开?感谢任何想法,如果我的理解不正确,请告诉我。

    最诚挚的问候,

1 个答案:

答案 0 :(得分:0)

同时使用initstart方法的原因如下。依赖项管理器允许您以声明方式定义(Java)代码中的组件及其依赖项。这可以在启动捆绑包时完成,但有时组件可能具有依赖于某些配置或其他依赖项之一的依赖关系。换句话说,您可能具有要在运行时添加到组件的依赖项。

在这种情况下,您可以做的是在组件实现上定义init(Component c)方法。在初始化组件并注入所有必需的依赖项(或调用它们的回调)之后,将调用此方法。那么在那时你可以访问组件中的这种依赖关系,你可以根据通过这种依赖关系获得的信息来决定动态添加另一个组件,如下所示:

public volatile OtherService s; // an injected service dependency

public void init(Component c) {
  if (s.needsSomeService()) {
    DependencyManager dm = c.getDependencyManager();
    c.add(dm.createServiceDependency()
      .setService(SomeService.class)
      .setInstanceBound(true)
      .setRequired(true));
  }
}

一旦SomeService可用,将调用start()方法并使您的组件可用(这意味着如果它发布服务,现在将完成)。

简而言之:存在init方法,允许您操作自己的组件定义并在运行时动态添加额外的依赖项。然后,一旦所有依赖项可用,就会调用start方法。

在没有这些要求的简单场景中,使用任一方法进行初始化都很好。