spring 当bean有多个接口时,如何弹出identity/autowires bean?

s4chpxco  于 2022-10-30  发布在  Spring
关注(0)|答案(2)|浏览(146)

假设我有接口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?

2guxujil

2guxujil1#

Spring的默认自动连接模式是按类型,所以如果创建两个iBar类型的bean,它们不会自动连接为iFoo,即使具体类也是iFoo的示例。Spring不知道一个类实现的所有接口,它只知道在其上下文中创建的bean的类型。
当您尝试自动连接List<<iFoo>>时,Spring将在其上下文中查找要注入的所有iFoo类型的bean,而您没有这些bean。
另外,请仔细阅读Java命名约定,您可能希望您的接口仅为FooBarhttps://www.oracle.com/java/technologies/javase/codeconventions-namingconventions.html

0pizxfdo

0pizxfdo2#

当声明带有@ Bean注解的方法的bean时,Spring将方法的返回类型赋值为bean类型,即将类名(ibar.class.getName())保存到BeanDefinition中,沿着保存其他对象元数据,从现在开始,Spring不关心你的类是否实现了其他接口,它只拥有你的对象和赋值的类型。
自动装配时,spring将过滤与Bean类型和名称约束(由要构造的Bean的类型提供)相匹配的Bean
在这种情况下,当尝试创建List<iFoo>时,spring可以挂钩具有类型iFoo或扩展/实现它的类型的bean,但不能挂钩ibar,因为ibariFoo无关
如果你只需要List<iFoo>,并且你没有使用fooBarOne/fooBarTwo bean,那么实际上你将bean声明为iFoo还是fooBarOne并不重要。但是一般来说,你应该更喜欢使用接口而不是实现,这将有助于在你的代码中保持依赖反转。
并且,始终用大写字母命名类。

相关问题