我的Liferay服务实现模块的两个实例

我的Liferay服务实现模块的两个实例,liferay,osgi,liferay-7,Liferay,Osgi,Liferay 7,我编写了一个模块来定义服务: public interface TranslationService { // a method. } 。。。实现该服务的模块: @Component( immediate = true, configurationPid = "my.TranslationConfiguration" ) public class TranslationServiceImpl implements TranslationService { lo

我编写了一个模块来定义服务:

public interface TranslationService {
    // a method.
}
。。。实现该服务的模块:

@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.
}
@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;
}
。。。以及使用该服务的模块:

@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.
}
@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;
}
日志 启动(通过Gogo Shell)API和实现模块时记录:

Constructor my.TranslationServiceImpl 606817095
Service registered.
STARTED my.impl_1.0.0 [538]
Constructor my.TranslationServiceImpl 362465287
Configuring my.TranslationServiceImpl 362465287
然后,当我启动(通过Gogo Shell)使用模块时:

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.(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(本机方法)
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(本机方法)
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.(TranslationServiceImpl.java:56)
sun.reflect.NativeConstructorAccessorImpl.newInstance0(本机方法)
sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
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(本机方法)
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)

看来我不应该在ServiceActivator中实例化实现?不过,在中似乎就是这样做的。

您将获得组件的第二个实例,因为您正在显式创建它,位于
ServiceActivator.java
的第24行。您发布的第一个堆栈跟踪显示了这一点

只要删除那行代码,一切都会好起来的

事实上,您可能根本不需要ServiceActivator。我假设它是您的捆绑包的
BundleActivator
?在使用DS时,您不需要编写激活器,因为您可以在激活器中执行任何操作
@Component(
    service = TranslationService.class,
    immediate = true,
    configurationPid = "my.TranslationConfiguration"
)
public class TranslationServiceImpl implements TranslationService {