繁体   English   中英

使用xml配置在spring boot中有条件地加载一个bean?

[英]Conditionally load a bean in spring boot using xml configuration?

我正在使用 Spring Boot 2.1。

我的项目中有一些混合配置:XML 文件和带有注释的 Java 类。 我们有这个有效的当前配置:

应用程序属性:

spring.profiles.active=dev, component1, component2

applicationContext-file.xml :

 <?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
  xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd"
  profile="component1"> 
    <beans>
        <bean id="myserviceimpl"
            class="org.blabla.MyServiceImpl">
            <property name="mydao">
                <ref bean="mydao"></ref>
            </property>
        </bean>
    </beans>
</beans>   

我们想从 spring.profiles.active 属性中提取组件值,因为它们与环境无关:

应用程序属性:

spring.profiles.active=dev
component1=true
component2=true

如何在 applicationContext-file.xml 中调节 myserviceimpl bean 的实例化? 我不能再依赖 profile 属性,因为 spring.profiles.active 属性不再包含组件的值。

谢谢你的帮助。

我自己没有尝试过,但我建议检查以下内容:

第1步

为每个配置文件创建一个 XML 文件(例如, devprod ):

app-config-dev.xml:
------------------

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
  xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd"
  profile="dev"> 
    <beans>
       <!-- here define only beans that you want to load in __dev__ environment -->
        <bean id="myserviceimpl"
            class="org.blabla.MyServiceImpl">
            <property name="mydao">
                <ref bean="mydao"></ref>
            </property>
        </bean>
    </beans>
</beans> 
app-config-prod.xml:
------------------

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
  xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd"
  profile="prod"> 
    <beans>
        <!-- here define only beans that you want to load in __production__ environment -->
        <bean id="myserviceimpl"
            class="org.blabla.MyServiceProdImpl">
            <property name="mydao">
                <ref bean="mydao"></ref>
            </property>
        </bean>
    </beans>
</beans> 

第2步

现在在您的“主要”applicationContext-file.xml 中,而不是直接定义 bean,包括您在步骤 1 中创建的所有 xml 文件:

<import resource="classpath:app-config-dev.xml" /> 
<import resource="classpath:app-config-prod.xml" /> 
  • 如果需要,请阅读此线程以获取有关此步骤的更多详细信息

第 3 步

从应用程序属性中删除component1=truecomponent2=true ,您不再需要它了,配置文件本身定义了应该加载哪些 bean。

更新 1

基于 OP 的第一条评论:

您可能可以尝试另一种选择,但我认为它是“低级”解决方案,它需要深入了解弹簧加载过程如何在幕后工作。

因此,当 spring 启动时,它会找到 bean 的定义(在 xml、java 配置、 @Component等注释中)并根据所有这些信息创建一个BeanDefinition一个聚合关于 bean 的所有信息的元数据对象(例如它的单例或原型)。 此时还没有创建任何bean。 让我们称这个时间点为“完成 Bean 定义”点”(为了解释起见,这是我的术语……

然后 spring 开始构建依赖关系图并开始创建 bean,初始化它们(自动装配、后构造方法等)并将它们放置到应用程序上下文中(如果它们是单例)。

现在,在 spring 中有一个选项可以提供一个名为BeanFactoryPostProcessor的钩子,该钩子恰好在“Bean Definitions Done”点调用。 这基本上是一个实现一些接口的java代码,它本身就是一个spring以特殊方式处理的spring bean。

所以你可以实现这个接口并操作Bean工厂的结果。 也就是说,您可以访问 spring 已打开的每个 bean 定义,并且如果您认为不应创建此定义的 bean(这里是您的自定义逻辑来检查属性,无论如何) - 从注册表中删除 bean 定义:对于技术方法删除 bean 定义请参阅此线程

是一个 Bean Factory Post 处理器的例子,它实际上添加了一个新的 bean,虽然它没有注册

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM