有没有人试图根据条件将不同的bean自动连接到Spring管理的bean?例如,如果满足某些条件,则注入A类,否则B?我在其中一个Google搜索结果中看到,使用SpEL(Spring Expression Language)可以实现,但无法找到一个有效的示例.
Pav*_*ral 84
有多种方法可以实现这一目标.大多数情况下,这取决于您想要执行的条件.
您可以实现简单的工厂bean来进行条件连接.这样的工厂bean可以包含复杂的条件逻辑:
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
}
Run Code Online (Sandbox Code Playgroud)
也许更好的方法是,如果你想在你的应用程序上下文中只有一个这样的bean的情况下使用工厂bean来创建依赖bean:
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
}
Run Code Online (Sandbox Code Playgroud)
使用SpEL有很多可能性.最常见的是基于系统属性的条件:
<bean class="com.example.MyBean">
<property name="dependency" value="#{systemProperties['foo'] == 'bar' ? dependencyX : dependencyY}" />
</bean>
Run Code Online (Sandbox Code Playgroud)
您可以让属性占位符解析您的bean引用.依赖项名称可以是应用程序配置的一部分.
<bean class="com.example.MyBean">
<property name="dependency" ref="${dependencyName}" />
</bean>
Run Code Online (Sandbox Code Playgroud)
通常,您要评估的条件意味着应该或不应该注册一整套bean.Spring配置文件可用于此:
<!-- 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>
Run Code Online (Sandbox Code Playgroud)
其他方法可以将bean定义标记为lazy-init="true",但定义仍将在应用程序上下文中注册(并且在使用非限定自动装配时使您的生活更加艰难).您还可以@Component通过@Profile注释使用基于bean的配置文件.
检查ApplicationContextInitialier(或此示例)以查看如何以编程方式激活配置文件(即根据您的条件).
这就是为什么基于Java的配置如此受欢迎的原因:
@Bean
public MyBean myBean() {
MyBean myBean = new MyBean();
if (true /* some condition */) {
myBean.setDependency(dependencyX());
} else {
myBean.setDependency(dependencyY());
}
return myBean;
}
Run Code Online (Sandbox Code Playgroud)
当然,你可以使用更多或更少的基于Java的配置所有的配置方法,以及(通过@Profile,@Value或@Qualifier+ @Autowired).
Spring提供了许多钩点和SPI,您可以在其中参与应用程序上下文生命周期.本节需要更多关于Spring内部工作的知识.
BeanFactoryPostProcessors可以读取和更改bean定义(例如,以${}这种方式实现属性占位符解析).
BeanPostProcessors可以处理bean实例.可以检查新创建的bean并使用它(例如,@Scheduled注释处理以这种方式实现).
MergedBeanDefinitionPostProcessor是bean后处理器的扩展,可以在实例化之前改变bean定义(@Autowired注释处理以这种方式实现).
2015年10月更新
Spring 4添加了一种新方法,如何通过注释进行条件bean注册@Conditional.这也值得一试.
当然,还有很多其他的方法可以通过它独自使用Spring Boot @ConditionalOn*.
另请注意,两者@Import和@ComponentScan(及其XML对应物)都经过属性解析(即您可以使用${}).
| 归档时间: |
|
| 查看次数: |
51565 次 |
| 最近记录: |