[英]How to get all beans of specified interface which also implements other interfaces
這里我有 3 個接口: InterfaceA
和InterfaceB
以及SharedInterface
public interface InterfaceA {
/**
* print some message
*/
void printMsg();
}
public interface InterfaceB {
/**
* print some message
*/
void printMsg();
}
public interface SharedInterface {
/**
* print some message
*/
void printSharedMsg();
}
這些接口有 3 個實現:
public class ImplementA1 implements InterfaceA, SharedInterface {
@Override
public void printMsg() {
System.out.println("this is message of interfaceA1");
}
@Override
public void printSharedMsg() {
System.out.println("this is shared message from ImplementA1");
}
}
public class ImplementA2 implements InterfaceA, SharedInterface {
@Override
public void printMsg() {
System.out.println("this is message of interfaceA2");
}
@Override
public void printSharedMsg() {
System.out.println("this is shared message from ImplementA2");
}
}
public class ImplementB implements InterfaceB, SharedInterface {
@Override
public void printMsg() {
System.out.println("this is message of interfaceB");
}
@Override
public void printSharedMsg() {
System.out.println("this is shared message from ImplementB");
}
}
ImplementA1
和ImplementA2
是同一類型的操作, ImplementB
是另一種類型的操作。 所以我決定開發 2 個配置 class 來注冊 ImplementA1、ImplementA2 和 ImplementB,如下所示。
@Configuration
public class InterfaceAConfig {
@Bean
public InterfaceA registerInterfaceA1(){
return new ImplementA1();
}
@Bean
public InterfaceA registerInterfaceA2(){
return new ImplementA2();
}
}
@Configuration
public class InterfaceBConfig {
@Bean
public InterfaceB registerInterfaceB(){
return new ImplementB();
}
}
現在我想讓所有實現SharedInterface
的 bean 在組件中打印它們的消息。 它運作良好,這是代碼:
@Component
@AutoConfigureAfter(value = {
InterfaceAConfig.class,
InterfaceBConfig.class})
public class SharedInterfaceComponent implements ApplicationListener<ContextRefreshedEvent>, ApplicationContextAware {
private ApplicationContext applicationContext;
//print shared message after IOC container refreshed
@Override
public void onApplicationEvent(ContextRefreshedEvent event) {
usingContextGetBean();
}
private void usingContextGetBean() {
Map<String, SharedInterface> beans = this.applicationContext.getBeansOfType(SharedInterface.class);
System.out.println(beans.size());
for (SharedInterface bean : beans.values()) {
bean.printSharedMsg();
}
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
}
但是我找到了另一種將 bean 注入組件的方法,使用
@Autowired
List<TargetType> myListName
所以我決定將我的SharedInterfaceComponent
更改為此以進行測試,並且它有效:
@Component
@AutoConfigureAfter(value = {
InterfaceAConfig.class,
InterfaceBConfig.class})
public class SharedInterfaceComponent implements ApplicationListener<ContextRefreshedEvent>, ApplicationContextAware {
private ApplicationContext applicationContext;
//todo why do spring failed due to this autowire?
@Autowired
private List<InterfaceA> autowiredList;
//print shared message after IOC container refreshed
@Override
public void onApplicationEvent(ContextRefreshedEvent event) {
usingAutowiredGerBean();
//usingContextGetBean();
}
private void usingAutowiredGerBean() {
for (InterfaceA interfaceA : autowiredList) {
if (SharedInterface.class.isAssignableFrom(interfaceA.getClass())){
((SharedInterface) interfaceA).printSharedMsg();
}
}
}
private void usingContextGetBean() {
Map<String, SharedInterface> beans = this.applicationContext.getBeansOfType(SharedInterface.class);
System.out.println(beans.size());
for (SharedInterface bean : beans.values()) {
bean.printSharedMsg();
}
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext=applicationContext;
}
}
但是當我嘗試使用SharedInterface
而不是InerfaceA
從 IOC 獲取 bean 時,它出錯了。 代碼如下所示:
@Component
@AutoConfigureAfter(value = {
InterfaceAConfig.class,
InterfaceBConfig.class})
public class SharedInterfaceComponent implements ApplicationListener<ContextRefreshedEvent>, ApplicationContextAware {
private ApplicationContext applicationContext;
//todo why do spring failed due to this autowire?
@Autowired
private List<SharedInterface> autowiredList;
//print shared message after IOC container refreshed
@Override
public void onApplicationEvent(ContextRefreshedEvent event) {
usingAutowiredGerBean();
//usingContextGetBean();
}
private void usingAutowiredGerBean() {
for (SharedInterface sharedInterface : autowiredList) {
if (SharedInterface.class.isAssignableFrom(sharedInterface.getClass())){
((SharedInterface) sharedInterface).printSharedMsg();
}
}
}
private void usingContextGetBean() {
Map<String, SharedInterface> beans = this.applicationContext.getBeansOfType(SharedInterface.class);
System.out.println(beans.size());
for (SharedInterface bean : beans.values()) {
bean.printSharedMsg();
}
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext=applicationContext;
}
}
在此演示中,應用程序將失敗並顯示
***************************
APPLICATION FAILED TO START
***************************
Description:
Field autowiredList in com.wwstation.test.config.SharedInterfaceComponent required a bean of type 'java.util.List' that could not be found.
The injection point has the following annotations:
- @org.springframework.beans.factory.annotation.Autowired(required=true)
Action:
Consider defining a bean of type 'java.util.List' in your configuration.
但是在我的其他項目中,同樣的情況不會導致迷戀,我可以通過使用@Autowired
來獲取SharedInterface
,但是在那里我只能獲取實現InterfaceA
或InterfaceB
的 beans,而不能全部實現。 我想,不崩潰的情況可能是我在其他項目中的一些依賴造成的。 誰能幫助我了解如何讓所有SharedInterface
更優雅? 非常感謝!
問題是你的配置。
@Bean
public InterfaceA registerInterfaceA1(){
return new ImplementA1();
}
這樣做的問題是 Spring 將使用該方法的返回類型來查看它是否填滿了注入點(在本例中為您的列表)。 由於InterfaceA
不是SharedInterface
最終它會失敗,因為沒有根據您的配置實現SharedInterface
的 bean。
您應該對自己的 bean 做的是在返回類型中盡可能具體。 因此,而不是InterfaceA
讓它返回實際的 class ImplementA1
和ImplementA2
。 這樣 Spring 在配置時可以確定那些實現SharedInterface
並使用它們來填充列表。
@Bean
public ImplementA1 registerInterfaceA1(){
return new ImplementA1();
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.