假设我有接口foo和bar,然后有多个实现这两个接口的类:
public interface InterfaceFoo{
int getFoo()
}
public interface InterfaceBar{
int getBar()
}
public class FooBarOne implements InterfaceFoo, InterfaceBar{
public int getFoo() { ... }
public int getBar() { ... }
}
public class FooBarTwo implements InterfaceFoo, InterfaceBar{
public int getFoo() { ... }
public int getBar() { ... }
}
然后我为这两个类创建bean:
@Configuration
@ComponentScan
public class Config {
@Bean
fooBarOne getFooBarOne() { return new FooBarOne(); }
@Bean
fooBarTwo getFooBarTwo() { return new FooBarTwo();}
}
最后还有一个bean,它在所有foo实现的列表中@Autowries
@Configuration
@ComponentScan
public class FooConfig {
@Bean
@Autowired
public List<InterfaceFoo> fooFetcher(List<<InterfaceFoo>> listFoos) {
return listFoos;
}
}
我的问题是,当bean有一个接口的多个实现时,Spring如何识别/autowire bean?上面的伪代码看起来是可行的,但是,如果我将bean的返回类型从concrete类更改为ibar,autowire就不会拾取它:
@Configuration
@ComponentScan
public class Config {
@Bean
InterfaceBar getFooBarOne() { return new FooBarOne(); }
@Bean
InterfaceBar getFooBarTwo() { return new FooBarOne(); }
}
从上面的例子中可以看出,spring在为ifoo的实现进行自动化时并没有选择这些bean,将返回类型切换为ifoo是可行的,这意味着spring会查看bean的返回类型,而不是返回对象的返回类型??即使fooBarOne和fooBarTwo都实现了foo和bar,如果我想让列表的autowire获取它,我需要返回具体类还是接口ifoo?
2条答案
按热度按时间2guxujil1#
Spring的默认自动连接模式是按类型,所以如果创建两个
iBar
类型的bean,它们不会自动连接为iFoo
,即使具体类也是iFoo
的示例。Spring不知道一个类实现的所有接口,它只知道在其上下文中创建的bean的类型。当您尝试自动连接
List<<iFoo>>
时,Spring将在其上下文中查找要注入的所有iFoo
类型的bean,而您没有这些bean。另外,请仔细阅读Java命名约定,您可能希望您的接口仅为
Foo
和Bar
https://www.oracle.com/java/technologies/javase/codeconventions-namingconventions.html0pizxfdo2#
当声明带有@ Bean注解的方法的bean时,Spring将方法的返回类型赋值为bean类型,即将类名(
ibar.class.getName()
)保存到BeanDefinition中,沿着保存其他对象元数据,从现在开始,Spring不关心你的类是否实现了其他接口,它只拥有你的对象和赋值的类型。自动装配时,spring将过滤与Bean类型和名称约束(由要构造的Bean的类型提供)相匹配的Bean
在这种情况下,当尝试创建
List<iFoo>
时,spring可以挂钩具有类型iFoo
或扩展/实现它的类型的bean,但不能挂钩ibar
,因为ibar
与iFoo
无关如果你只需要
List<iFoo>
,并且你没有使用fooBarOne
/fooBarTwo
bean,那么实际上你将bean声明为iFoo
还是fooBarOne
并不重要。但是一般来说,你应该更喜欢使用接口而不是实现,这将有助于在你的代码中保持依赖反转。并且,始终用大写字母命名类。