在Spring的 XML配置中,根据一个在应用启动时才会确定的属性有条件地创建Bean
我有一个相当老的Java Spring应用,bean在 XML中定义。我需要有条件地禁用其中一个bean(这是一个指向将被关闭的数据库服务器的DBCP2数据源),所以我真正想做的,大概是像下面这样
<beans>
<bean id="beanA" />
<bean id="beanB" />
<bean id="beanC" onlyif="#{some expression}" />
</beans>
但我找不到除了
<beans>
<bean id="beanA" />
<bean id="beanB" />
<beans profile="activateBeanC">
<bean id="beanC" />
</beans>
</beans>
之外的办法……这没问题,但接下来问题是,如何激活profile?(某个表达式)相当复杂,而且只能在其他某些bean实例化之后才会被求值,所以我不能
if (some expression)
System.setProperty ("spring.profiles.active", "activateBeanC");
new ClassPathXmlApplicationContext ("spring-beans.xml");
我也尝试过类似的
<beans>
<bean class="MethodInvokingBean">
<property name="targetClass" value="ConfigureSpringProfiles" />
<property name="targetMethod" value="configureSpringProfiles" />
<property name="arguments">
<list>
<value>${some expression}</value>
</list>
</property>
</bean>
<bean id="beanA" />
<bean id="beanB" />
<beans profile="activateBeanC">
<bean id="beanC" />
</beans>
</beans>
public void configureSpringProfiles(boolean activateBeanC) {
if (activateBeanC)
System.setProperty ("spring.profiles.active", "activateBeanC");
}
我可以看到 configureSpringProfiles() 被正确调用,传入了正确的参数值并按需调用setProperty(或不调用),但它不起作用,因为它在Spring应用尚处于启动过程时就试图激活该profile。
解决方案
我在Spring里没有找到解决这个问题的答案。我发现的是,我原以为既然你给DBCP2 BasicDataSource提供了一个 "validationQuery" 来测试数据库连接是否正常,我以为在应用启动/ bean创建时,它会对数据库进行一次测试连接,以证明其用户名/密码等在应用启动前就能用。结果并非如此(可能是因为initialSize = 0),它不会在应用启动时就去连接,直到应用中的某些东西实际尝试使用数据源。因此其实我并不需要阻止Spring创建数据源bean,只要能阻止应用尝试使用它,这要简单得多。
所以我只是按下面的方式在数据源上设置属性(省略与问题无关的部分)
<bean class="org.apache.commons.dbcp2.BasicDataSource">
<property name="username" value="#{some expression ? realUsername : null}" />
<property name="password" value="#{some expression ? realPassword : null}" />
<property name="url" value="#{some expression ? realUrl : null}" />
<property name="initialSize" value="0" />
<property name="validationQuery" value="1" />
</bean>
只要你实际不去使用数据源,它就不会因为“你的用户名/密码/URL无效”而抛出异常。
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。