1. 程式人生 > >使用dubbo對外暴露介面,實現類同時實現兩個介面後 @Autowire失敗,提示expected single matching bean but found 2解決方案

使用dubbo對外暴露介面,實現類同時實現兩個介面後 @Autowire失敗,提示expected single matching bean but found 2解決方案

當使用dubbo對外暴露介面時,為了方便繼承和實現底層方法,另一方面專門對外提供一套介面方法,這時介面實現類同時實現了兩個介面:
@Service("ICentAccountInfoService")
public class CentAccountInfoServiceImpl
        extends AbstractPageService<IBaseDAO<CentAccountInfo>, CentAccountInfo>
        implements
        ICentAccountInfoService<IBaseDAO<CentAccountInfo
>,CentAccountInfo>, CentAccountInfoServiceAPI {
@Autowired private CentAccountInfoDAO centAccountInfoDAO; @Override public IBaseDAO<CentAccountInfo> getDao() { return null; } //實現 ICentAccountInfoService 方法 public
int insert(CentAccountInfo cent){ System.out.println("==== insert in!"); int result = centAccountInfoDAO.insert(cent); return result; } //實現對外業務介面 CentAccountInfoServiceAPI 方法 @Override public void showMembers() { System.out.println("==== show members!!"
); } }

dubbo對外暴露服務是這樣處理的:

<dubbo:service  interface="cn.qtone.xxt.api.CentAccountInfoServiceAPI"
                   ref="CentAccountInfoServiceAPI" executes="100" timeout="600000" retries="0" />
    <bean id="CentAccountInfoServiceAPI" class="cn.qtone.xxt.cent.service.Impl.CentAccountInfoServiceImpl" />

對外暴露的介面:

public interface CentAccountInfoServiceAPI
{
    public void showMembers();
}

現在用Junit測試看看:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath*:applicationContext.xml")
public class CentAccountInfoServiceTest{

    @Autowired
//    @Qualifier("ICentAccountInfoService")
    private CentAccountInfoServiceImpl centAccountInfoService;

    @Test
    public void test(){
        //showcase
//        Assert.assertEquals(1, centAccountInfoService.findAll().size());
        CentAccountInfo cent = new CentAccountInfo();
        cent.setPhone("13377777777");
        cent.setCreateTime(new Date());
        Assert.assertEquals(1, centAccountInfoService.insert(cent));    //impl實現的介面  ICentAccountInfoService 中的方法
        centAccountInfoService.showMembers();  //impl實現的介面  CentAccountInfoServiceAPI  中的方法

    }
}

但測試結果報錯,提示:

Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: private cn.qtone.xxt.cent.service.Impl.CentAccountInfoServiceImpl cn.qtone.xxt.test.service.CentAccountInfoServiceTest.centAccountInfoService; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No unique bean of type [cn.qtone.xxt.cent.service.Impl.CentAccountInfoServiceImpl] is defined: expected single matching bean but found 2: [ICentAccountInfoService, CentAccountInfoServiceAPI]
...(省略)
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No unique bean of type [cn.qtone.xxt.cent.service.Impl.CentAccountInfoServiceImpl] is defined: expected single matching bean but found 2: [ICentAccountInfoService, CentAccountInfoServiceAPI]
    ... 31 more

查了下這個問題,發現在使用Spring框架中@Autowired標籤時預設情況下使用 @Autowired 註釋進行自動注入時,Spring 容器中匹配的候選 Bean 數目必須有且僅有一個。當找不到一個匹配的 Bean 時,Spring 容器將拋BeanCreationException 異常,並指出必須至少擁有一個匹配的 Bean。
這時的解決辦法就是:
通過 @Qualifier 註釋指定注入 Bean 的名稱,這樣歧義就消除了。

只需要加一行程式碼,這個問題迎刃而解:

  @Autowired
    @Qualifier("ICentAccountInfoService")
    private CentAccountInfoServiceImpl centAccountInfoService;

測試結果:
這裡寫圖片描述

驗證ok!