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