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