2017-08-25 72 views
1

我寫了定義一個服務模塊:兩個實例

​​

...實現服務模塊:

@Component(
    immediate = true, 
    configurationPid = "my.TranslationConfiguration" 
) 
public class TranslationServiceImpl implements TranslationService { 

    log.info("Constructor " + getClass().getName() 
      + " " + System.identityHashCode(this)); 

    @Activate 
    @Modified 
    protected void activate(Map<String, Object> properties) { 
     log.info("Configuring " + translationService.getClass().getName() 
       + " " + System.identityHashCode(this)); 
     configuration = ConfigurableUtil.createConfigurable(
      TranslationConfiguration.class, properties); 
} 

    // an implementation of the method. 
} 

其服務激活:

public class ServiceActivator implements BundleActivator { 

    private ServiceRegistration registration; 

    @Override 
    public void start(BundleContext context) throws Exception { 
     registration = context.registerService(TranslationService.class.getName(), new TranslationServiceImpl(), null); 
    } 

    [...] 
} 

...和使用該服務的模塊:

@Component(
    immediate = true, 
    configurationPid = [...] 
    service = Portlet.class 
) 
public class TranslationPortlet extends MVCPortlet { 

    @Reference(unbind = "-") 
    protected void setTranslationService(TranslationService translationService) { 
     log.info("Using " + translationService.getClass().getName() 
       + " " + System.identityHashCode(translationService)); 
     this.translationService = translationService; 
    } 

    private TranslationService translationService; 
} 

登錄

登錄時開始(通過勾勾殼牌)的API和執行模塊:

Constructor my.TranslationServiceImpl 606817095 
Service registered. 
STARTED my.impl_1.0.0 [538] 
Constructor my.TranslationServiceImpl 362465287 
Configuring my.TranslationServiceImpl 362465287 

然後,當開始(通過勾勾殼牌)的使用模塊:

STARTED my.app_1.0.0 [558] 
Using my.TranslationServiceImpl 606817095 

問題

爲什麼使用兩個實例?
如何使所有模塊使用我的服務實現的相同實例?

詳細

兩個時代的蹤跡執行調用構造函數:

my.TranslationServiceImpl.<init>(TranslationServiceImpl.java:56) 
my.ServiceActivator.start(ServiceActivator.java:24) 
org.eclipse.osgi.internal.framework.BundleContextImpl$3.run(BundleContextImpl.java:774) 
org.eclipse.osgi.internal.framework.BundleContextImpl$3.run(BundleContextImpl.java:1) 
java.security.AccessController.doPrivileged(Native Method) 
org.eclipse.osgi.internal.framework.BundleContextImpl.startActivator(BundleContextImpl.java:767) 
org.eclipse.osgi.internal.framework.BundleContextImpl.start(BundleContextImpl.java:724) 
org.eclipse.osgi.internal.framework.EquinoxBundle.startWorker0(EquinoxBundle.java:951) 
org.eclipse.osgi.internal.framework.EquinoxBundle$EquinoxModule.startWorker(EquinoxBundle.java:328) 
org.eclipse.osgi.container.Module.doStart(Module.java:566) 
org.eclipse.osgi.container.Module.start(Module.java:434) 
org.eclipse.osgi.internal.framework.EquinoxBundle.start(EquinoxBundle.java:402) 
org.apache.felix.gogo.command.Basic.start(Basic.java:729) 
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) 
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 
java.lang.reflect.Method.invoke(Method.java:498) 
org.apache.felix.gogo.runtime.Reflective.invoke(Reflective.java:137) 

然後:

my.TranslationServiceImpl.<init>(TranslationServiceImpl.java:56) 
sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) 
sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62) 
sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) 
java.lang.reflect.Constructor.newInstance(Constructor.java:423) 
java.lang.Class.newInstance(Class.java:442) 
org.apache.felix.scr.impl.manager.SingleComponentManager.createImplementationObject(SingleComponentManager.java:236) 
org.apache.felix.scr.impl.manager.SingleComponentManager.createComponent(SingleComponentManager.java:108) 
org.apache.felix.scr.impl.manager.SingleComponentManager.getService(SingleComponentManager.java:906) 
org.apache.felix.scr.impl.manager.SingleComponentManager.getServiceInternal(SingleComponentManager.java:879) 
org.apache.felix.scr.impl.manager.AbstractComponentManager.activateInternal(AbstractComponentManager.java:748) 
org.apache.felix.scr.impl.manager.AbstractComponentManager.enableInternal(AbstractComponentManager.java:674) 
org.apache.felix.scr.impl.manager.AbstractComponentManager.enable(AbstractComponentManager.java:429) 
org.apache.felix.scr.impl.manager.ConfigurableComponentHolder.enableComponents(ConfigurableComponentHolder.java:657) 
org.apache.felix.scr.impl.BundleComponentActivator.initialEnable(BundleComponentActivator.java:341) 
org.apache.felix.scr.impl.Activator.loadComponents(Activator.java:403) 
org.apache.felix.scr.impl.Activator.access$200(Activator.java:54) 
org.apache.felix.scr.impl.Activator$ScrExtension.start(Activator.java:278) 
org.apache.felix.utils.extender.AbstractExtender.createExtension(AbstractExtender.java:259) 
org.apache.felix.utils.extender.AbstractExtender.modifiedBundle(AbstractExtender.java:232) 
org.osgi.util.tracker.BundleTracker$Tracked.customizerModified(BundleTracker.java:482) 
org.osgi.util.tracker.BundleTracker$Tracked.customizerModified(BundleTracker.java:1) 
org.osgi.util.tracker.AbstractTracked.track(AbstractTracked.java:232) 
org.osgi.util.tracker.BundleTracker$Tracked.bundleChanged(BundleTracker.java:444) 
org.eclipse.osgi.internal.framework.BundleContextImpl.dispatchEvent(BundleContextImpl.java:905) 
org.eclipse.osgi.framework.eventmgr.EventManager.dispatchEvent(EventManager.java:230) 
org.eclipse.osgi.framework.eventmgr.ListenerQueue.dispatchEventSynchronous(ListenerQueue.java:148) 
org.eclipse.osgi.internal.framework.EquinoxEventPublisher.publishBundleEventPrivileged(EquinoxEventPublisher.java:165) 
org.eclipse.osgi.internal.framework.EquinoxEventPublisher.publishBundleEvent(EquinoxEventPublisher.java:75) 
org.eclipse.osgi.internal.framework.EquinoxEventPublisher.publishBundleEvent(EquinoxEventPublisher.java:67) 
org.eclipse.osgi.internal.framework.EquinoxContainerAdaptor.publishModuleEvent(EquinoxContainerAdaptor.java:102) 
org.eclipse.osgi.container.Module.publishEvent(Module.java:461) 
org.eclipse.osgi.container.Module.start(Module.java:452) 
org.eclipse.osgi.internal.framework.EquinoxBundle.start(EquinoxBundle.java:402) 
org.apache.felix.gogo.command.Basic.start(Basic.java:729) 
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) 
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 
java.lang.reflect.Method.invoke(Method.java:498) 
org.apache.felix.gogo.runtime.Reflective.invoke(Reflective.java:137) 

因此,它好像我不應該實例在服務激活實施?不過,這似乎是在this tutorial中完成的。

+0

這看起來不可能。你有沒有看到一行說「配置my.TranslationServiceImpl 1451438505」? –

+0

你可以用構造函數記錄仔細檢查嗎? –

+0

@NeilBartlett:我添加了更多的細節,還有構造函數日誌。此外,我意識到我的服務激活可能導致問題,但我不知道如何改變它。非常感謝! –

回答

3

您正在獲取組件的第二個實例,因爲您明確地在ServiceActivator.java的第24行創建了它。這是通過您發佈的第一個堆棧跟蹤顯示的。

只需刪除該行代碼,一切都會好的。

事實上,您可能根本不需要ServiceActivator。我認爲它是你的包的BundleActivator?使用DS時不需要編寫激活器,因爲激活器中可以執行的任何操作都可以在DS組件中完成,還有更多。事實上,我的一般建議是不寫束激活器。

+0

糟糕我錯過了您發佈ServiceActivator.java的代碼的事實。是的,你絕對不需要這個。只要刪除它。 –

2

尼爾已經找到了答案,我只想補充一些細節:

正如尼爾說,不需要服務激活,儘管有什麼建議我掛在我的問題的教程。只要刪除它。

顯然,也可以從bnd.bnd中刪除Bundle-Activator:行,否則在部署時會出現Bundle-Activator not found on the bundle class path nor in imports錯誤。

尼爾在談到關於服務激活的地方時,使用了「DS」這個東西。它意味着聲明式服務,並且是一種與註釋一起使用的OSGi技術。要使用它,只需在實現類的@Component批註中添加service =指令,並將實現的服務(API)的接口作爲值。例如:

@Component(
    service = TranslationService.class, 
    immediate = true, 
    configurationPid = "my.TranslationConfiguration" 
) 
public class TranslationServiceImpl implements TranslationService { 
+1

嘿,我看了你鏈接的教程,看起來不太好。我們在OSGi中遇到的一個問題是,有一百萬個教程是由人們寫的,坦率地說,在嘗試教授之前需要學習更多。但作爲一個初學者,很難說哪些教程好,哪些是垃圾。 FWIW我不認爲這個「proliferay.com」網站與Liferay有任何關係,可能會侵犯他們的商標權。 –