在Spring的 XML配置中,根据一个在应用启动时才会确定的属性有条件地创建Bean

后端开发 2026-07-09

我有一个相当老的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导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章