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