如何在春季做条件自动布线?
有没有人试图根据条件将不同的bean自动连接到Springpipe理的bean? 例如,如果满足一些条件,注入类A,否则B? 我在其中一个Googlesearch结果中看到使用SpEL(Spring Expression Language)是可能的,但是找不到一个可行的例子。
有多种方法来实现这一点。 大多数情况下,这取决于你想要执行的条件。
工厂bean
你可以实现简单的工厂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 }
如果你想在你的应用程序上下文中只有一个这样的bean的话,使用factory bean来创build依赖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 }
规划环境地政司
使用SpEL有许多可能性。 最常见的是基于系统属性的条件:
<bean class="com.example.MyBean"> <property name="dependency" value="#{systemProperties['foo'] == 'bar' ? dependencyX : dependencyY}" /> </bean>
属性占位符
你可以让属性占位符parsing你的bean引用。 依赖项名称可以是应用程序configuration的一部分。
<bean class="com.example.MyBean"> <property name="dependency" ref="${dependencyName}" /> </bean>
spring概况
通常情况下,你想评估的条件意味着一整套的豆应该或不应该注册。 springconfiguration文件可以用于这个:
<!-- 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>
其他方法可以将bean定义标记为lazy-init="true"
,但定义将仍然在应用程序上下文中注册(并且在使用不合格的自动assembly时使生活更加困难)。 您还可以通过@Profile
注释使用基于@Component
的bean的configuration文件。
检查ApplicationContextInitialier
(或这个例子 ),看看如何以编程方式激活configuration文件(即根据您的条件 )。
Javaconfiguration
这就是为什么基于Java的configuration如此受欢迎,因为你可以这样做:
@Bean public MyBean myBean() { MyBean myBean = new MyBean(); if (true /* some condition */) { myBean.setDependency(dependencyX()); } else { myBean.setDependency(dependencyY()); } return myBean; }
当然你也可以在基于java的configuration中使用或多或less的所有configuration方法(通过@Value
, @Value
或者@Qualifier
+ @Autowired
)。
后处理器
Spring提供了许多钩点和SPI,您可以在其中参与应用程序上下文的生命周期。 这部分需要更多的关于Spring内部工作的知识。
BeanFactoryPostProcessor
可以读取和修改bean的定义(例如,属性占位符${}
是以这种方式实现的)。
BeanPostProcessor
可以处理bean实例。 可以检查刚刚创build的bean并使用它(例如@Scheduled
注释处理是以这种方式实现的)。
MergedBeanDefinitionPostProcessor
是bean后期处理器的扩展,可以在实例化之前改变bean的定义( @Autowired
注解处理是以这种方式实现的)。
更新2015年10月
-
Spring 4增加了一个新的方法,通过
@Conditional
注释来实现条件bean的注册 。 这也值得检查。 -
当然,通过它的
@ConditionalOn*
单独使用Spring Boot还有很多其他的方法。 -
还要注意,
@Import
和@ComponentScan
(及其XML对应)都经过属性parsing(即可以使用${}
)。
- 将applicationContext分割为多个文件
- 什么是Spring中的Dispatcher Servlet?
- 当find多个匹配的bean时,Spring如何通过名称自动装载?
- Spring MVCtypes转换:PropertyEditor或Converter?
- 为什么DispatcherServlet创build另一个应用程序上下文?
- Spring 3.1 entityManagerFactory java.lang.NoSuchFieldError:NULL错误
- Spring注解@Repository和@Service
- 我可以在哪里下载Spring Framework jars而不使用Maven?
- Spring的GA,RC和M2版本有什么区别?