Tuscany implementation.spring中@Service注解实现多重接口的...

问题描述

Tuscany中的@Service注解中定义的value属性是个Class数组,注解的源码如下:


@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发现了下面这段话:

// 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属性,则使用接口类的短名。

附测试代码:

@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的链接已经失效了,不知道是已经解决了还是什么原因。

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




转载于:https://my.oschina.net/hotleave/blog/137323

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值