public MyBeanFactoryBean implements FactoryBean<MyBean> {
// Using app context instead of bean references so that the unused
// dependency can be left uninitialized if it is lazily initialized
@Autowired
private ApplicationContext applicationContext;
public MyBean getObject() {
MyBean myBean = new MyBean();
if (true /* some condition */) {
myBean.setDependency(applicationContext.getBean(DependencyX.class));
} else {
myBean.setDependency(applicationContext.getBean(DependencyY.class));
}
return myBean;
}
// Implementation of isSingleton => false and getObjectType
}
public MyDependencyFactoryBean implements FactoryBean<MyDependency> {
public MyDependency getObject() {
if (true /* some condition */) {
return new MyDependencyX();
} else {
return new MyDependencyY();
}
}
// Implementation of isSingleton => false and getObjectType
}
<!-- Default dependency which is referred by myBean -->
<bean id="dependency" class="com.example.DependencyX" />
<beans profile="myProfile">
<!-- Override `dependency` definition if myProfile is active -->
<bean id="dependency" class="com.example.DependencyY" />
</beans>
1 回答
有多种方法可以实现这一目标 . 大多数情况下,这取决于您想要执行的条件 .
工厂bean
您可以实现简单的工厂bean来进行条件连接 . 这样的工厂bean可以包含复杂的条件逻辑:
也许更好的方法是,如果你想在你的应用程序上下文中只有一个这样的bean的情况下使用工厂bean来创建依赖bean:
SpEL
使用SpEL有很多可能性 . 最常见的是基于system property的条件:
属性占位符
您可以让属性占位符解析您的bean引用 . 依赖项名称可以是应用程序配置的一部分 .
Spring Profiles
通常,您要评估的条件意味着应该或不应该注册一整套bean . Spring配置文件可用于此:
其他方法可以将bean定义标记为
lazy-init="true"
,但该定义仍将在应用程序上下文中注册(并且在使用非限定自动装配时会使您的生活更加艰难) . 您还可以通过@Profile
注释使用基于@Component
的bean的配置文件 .检查ApplicationContextInitialier(或此example)以查看如何以编程方式激活配置文件(即根据您的条件) .
Java配置
这就是为什么基于Java的配置如此受欢迎的原因:
当然,您也可以在基于java的配置中使用或多或少的所有配置方法(通过
@Profile
,@Value
或@Qualifier
@Autowired
) .后处理器
Spring提供了许多钩点和SPI,您可以在其中参与应用程序上下文生命周期 . 本节需要更多关于Spring内部工作的知识 .
BeanFactoryPostProcessor
s可以读取和更改bean定义(例如,属性占位符${}
resolution以这种方式实现) .BeanPostProcessor
s可以处理bean实例 . 可以检查新创建的bean并使用它(例如@Scheduled
注释处理以这种方式实现) .MergedBeanDefinitionPostProcessor
是bean post processor的扩展,可以在实例化之前改变bean定义(@Autowired
注释处理以这种方式实现) .UPDATE Oct 2015
Spring 4添加了一个新方法conditional bean registration来自@Conditional注释 . 这也值得一试 .
当然,通过其
@ConditionalOn*
单独使用Spring Boot还有很多其他方法 .另请注意,
@Import
和@ComponentScan
(及其XML对应物)都经过属性解析(即您可以使用${}
) .