Tuscany implementation.spring中@Service註解實現多重接口的...

問題描述

Tuscany中的@Service註解中定義的value屬性是個Class數組,註解的源碼以下: html


@Target(TYPE)
@Retention(RUNTIME)
public @interface Service {

    /**
     * The value is an array of interface or class objects that should be
     * exposed as services by this component.
     *
     * @return the services of this component
     */
    Class<?>[] value();

    /**
     * The value is an array of strings which are used as the service names
     * for each of the interfaces declared in the value array.
     *
     * @return the service names
     */
    String[] names() default {};
}
從源碼中能夠看出,Service註解是支持多接口的。可是當實現了多個接口的bean被定義,使用<implementation.spring/>時,運行時卻會報出服務命名衝突的錯誤:
@Service(value = {Helloworld.class, I18NHelloworld.class}, names = {"Helloworld", "I18NHelloworld"})
public class HelloworldImpl implements Helloworld, I18NHelloworld {

    @Override
    public String sayHello(String name) {
        return "Hello " + name;
    }

    @Override
    public String sayI18nHello(String name) {
        return "International Hello " + name;
    }

    @Init
    public void init() {
        System.out.println("service inited");
    }

    @Destroy
    public void destroy() {
        System.out.println("service stoped");
    }
}
嚴重: [ASM40003,ASM60003,JCA90045] Duplicate implementation service name: Component = HelloworldComponent Service = helloworldImpl


解決方法

通過仔細排查,在Tuscany的tuscany-base-runtime-2.0-sources.jar!/org/apache/tuscany/sca/implementation/spring/introspect/SpringXMLComponentTypeLoader.java:467發現了下面這段話: java

// Set the service name as bean name
for (Service componentService : beanComponentType.getServices()) {
    componentService.setName(beanElement.getId());
}
不知道開發人員是出於什麼目的非要把服務名稱修改成springBean的ID,嘗試修改這段代碼爲如下內容後,一切工做正常
List<Service> serviceList = beanComponentType.getServices();
if (serviceList.size() == 1) {
   // Set the service name as bean name
   serviceList.get(0).setName(beanElement.getId());
}
若是@Service註解中提供了names屬性,則使用用戶提供的names屬性(如上面的代碼),若是沒有提供names屬性,則使用接口類的短名。

附測試代碼: node

@Test
    public void testSayHello() throws NoSuchServiceException {

        // Run the SCA composite in a Tuscany runtime
        Node node = TuscanyRuntime.runComposite("helloworld.composite", "target/classes");
        try {
            
            // Get the Helloworld service proxy
            Helloworld helloworld = node.getService(Helloworld.class, "HelloworldComponent/Helloworld");

            // test that it works as expected
            Assert.assertEquals("Hello Amelia", helloworld.sayHello("Amelia"));

            I18NHelloworld i18NHelloworld = node.getService(I18NHelloworld.class, "HelloworldComponent/I18NHelloworld");
            Assert.assertEquals("International Hello Amelia", i18NHelloworld.sayI18nHello("Amelia"));

            
        } finally {
            // Stop the Tuscany runtime Node
            node.stop();        
        }
    }

後記

在Tuscany官網的說明文檔中(連接頁面尾部的Non-Supported Features in Tuscany中提到的場景3),明確指出不支持實現了多重接口的Bean的服務暴露,可是JIRA的連接已經失效了,不知道是已經解決了仍是什麼緣由。 spring

連接地址:http://tuscany.apache.org/documentation-2x/sca-java-implementationspring.html apache

相關文章
相關標籤/搜索