![](/img/trans.png)
[英]Spring Autowire Bean with multiple Interface Implementations, define Implementation in method
[英]Spring Autowire Annotation with Several Interface Implementations
假设您有一个界面
public interface A {
public void doSomething();
}
和两个实现类
@Component(value="aImpl1")
public class AImpl1 implements A {
}
@Component(value="aImpl2")
public class AImpl2 implements A{
}
最后一个将使用“A”实现的类:
@Component
public class MyClass {
@Autowire
A a;
}
现在,如果我想注入AImpl1,我添加@Qualifier(“aImpl1”) ,如果我想注入AImpl2,我添加@Qualifier(“aImpl2”)
问题是:是否有可能以某种方式指示spring查找“A”的所有实现,在这种情况下是AImpl1和AImpl2,并使用一些特定于应用程序的约定来选择最合适的实现? 例如,在这种情况下,我的约定可以使用具有最大后缀的实现(即AImpl2)?
编辑:类MyClass根本不应该知道实现查找逻辑,它应该只找到它的属性“a”设置与AImpl2的对象。
您可以将所有实现注入List
:
@Autowired
List<A> as;
或者以bean名称作为键的Map
:
@Autowired
Map<String, A> as;
然后手动选择正确的实现(也许,在setter方法中):
@Autowired
public void setAs(Map<String, A> as) {
this.a = ...;
}
假设您已经拥有数百个接口和实现(正如您在评论中所说的那样),并且您不想重构所有代码......那么这是一个棘手的问题......这是一个棘手的解决方案:
您可以创建自定义BeanDefinitionRegistryPostProcessor
并实现方法postProcessBeanDefinitionRegistry
或postProcessBeanFactory
。
这样,您可以在实例化和注入之前访问所有 bean定义。 您的逻辑是为了找到每个接口的首选实现,然后将其设置为主要接口 。
@Component
public class CustomBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {
@Override
public void postProcessBeanDefinitionRegistry(
BeanDefinitionRegistry registry) throws BeansException {
// this method can be used to set a primary bean, although
// beans defined in a @Configuration class will not be avalable here.
}
@Override
public void postProcessBeanFactory(
ConfigurableListableBeanFactory beanFactory) throws BeansException {
// here, all beans are available including those defined by @configuration, @component, xml, etc.
// do some magic to somehow find which is the preferred bean name for each interface
// you have access to all bean-definition names with: beanFactory.getBeanDefinitionNames()
String beanName = "aImpl2"; // let's say is this one
// get the definition for that bean and set it as primary
beanFactory.getBeanDefinition(beanName).setPrimary(true)
}
}
困难的部分是找到bean名称,它取决于您的应用程序的细节。 我想拥有一致的命名约定会有所帮助。
更新:
似乎接口BeanDefinitionRegistryPostProcessor
中的两个方法都可用于此目的。 请记住,在postProcessBeanDefinitionRegistry
阶段,通过@configuration类配置的bean尚不可用,如下面的注释中所述。
另一方面,它们确实可以在postProcessBeanFactory
。
如果您有一个Configuration类,则可以使用其中的方法来决定返回哪个A实现。 然后autowired将为该类注入适当的实例。
@Configuration
public class ApplicationConfiguration {
@Bean
A getA() {
// instantiate the implementation of A that you would like to have injected
// or you could use reflection to find the correct class from the classpath.
// return the instance
}
}
这假设您总是希望在注入A的任何地方使用相同的实例。如果没有,那么您可以使用带有名称的不同@Bean注释方法来获得不同的版本。
您可以尝试使用Spring Profiles 。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.