关于classpath中有多个同名类或一个接口有多个实现类Spring启动失败总结

存在同名类

工程中(含依赖jar包) 若有两个同名的类,Spring启动时会报错 如下所示

main├── java│   └── com│           ├── bar│           │   └── service│           │       └── FooService.java│           └── foo│               └── service│                   └── FooService.java

工程中含两个同名的FooService 启动时会报错

Caused by: org.springframework.context.annotation.ConflictingBeanDefinitionException: Annotation-specified bean name 'fooService' for bean class [com.foo.service.FooService] conflicts with existing, non-compatible bean definition of same name and class [com.bar.service.FooService]    at org.springframework.context.annotation.ClassPathBeanDefinitionScanner.checkCandidate(ClassPathBeanDefinitionScanner.java:314)

解决方法

给任一FooService取个别名即可 如

@Service("anotherFooService")

此时可以正常启动。并且注入(@Autowired)的时候 也无需显式指定别名 即正常注入即可 如下所示

@RunWith(SpringJUnit4ClassRunner.class)@ContextConfiguration(locations = { "classpath:spring/ApplicationContextTest.xml" })public class FooService1Test{    @Autowired    private FooService service; // 使用的是foo包下的    @Test    public void test_doSomething(){        String s = service.doSomething();        Assert.assertEquals("com.foo.service.FooService",s);    }}@RunWith(SpringJUnit4ClassRunner.class)@ContextConfiguration(locations = {"classpath:spring/ApplicationContextTest.xml"})public class FooService2Test {    @Autowired    private FooService service; // 使用的是bar目录下的    @Test    public void test_doSomething() {        String s = service.doSomething();        Assert.assertEquals("com.bar.service.FooService", s);    }}

上面两个测试均能测试通过。 可见无需显式指定别名。该怎么用就怎么用。

什么情况下需要显式指定别名呢?

存在多个实现类

一个接口有两个实现 如下所示

  main/java└── com        ├── bar        │   └── service        │       ├── FooBarServiceImpl2.java        ├── foo        │   └── service        │       ├── FooBarServiceImpl1.java        └── service            └── IFooBarService.java

注入的时候使用的是接口名称 如下所示

@RunWith(SpringJUnit4ClassRunner.class)@ContextConfiguration(locations = { "classpath:spring/ApplicationContextTest.xml" })public class FooBarServiceTest {    @Autowired    private IFooBarService service; //使用的是接口名称    @Test    public void test_doSomething(){    }}

此时Spring启动会报错

Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [com.service.IFooBarService] is defined: expected single matching bean but found 2: fooBarServiceImpl2,fooBarServiceImpl1    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:970)

这种情况下需要显式指定别名 如下所示

@RunWith(SpringJUnit4ClassRunner.class)@ContextConfiguration(locations = { "classpath:spring/ApplicationContextTest.xml" })public class FooBarServiceTest {    @Autowired    @Qualifier("fooBarServiceImpl2")    private IFooBarService service;    @Test    public void test_doSomething(){        String s = service.doSomething();        Assert.assertEquals("com.bar.service.FooBarServiceImpl2",s);    }}

总结

异常
解释
解决

ConflictingBeanDefinitionException
表示类名冲突了
给任一类指定一个别名 如@Service("anotherFooService")

NoUniqueBeanDefinitionException
表示有多个候选类可用
注入时显式指定用哪一个 如 @Autowired @Qualifier("fooBarServiceImpl2")

关键字:spring, autowired

版权声明

本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处。如若内容有涉嫌抄袭侵权/违法违规/事实不符,请点击 举报 进行投诉反馈!

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部