【问题标题】:Setting a Spring bean class name using a SpEL expression and PropertyPlaceHolder使用 SpEL 表达式和 PropertyPlaceHolder 设置 Spring bean 类名
【发布时间】:2012-03-28 12:48:14
【问题描述】:

更新:截至 2016 年 12 月 9 日的决议摘要

根据下面@altazar 的回答,this is now possible 从 Spring 4.2 开始!

截至 2012 年 3 月 29 日的旧决议摘要

截至目前,Spring SpEL 无法在classclass 属性内执行<bean>

原问题:

我正在尝试为 Spring bean 实现动态 class 属性,最终使用 PropertyPlaceHolder 属性和 SpEL 表达式的组合进行设置。目的是选择要实例化的类的生产版本或调试版本。它不起作用,我想知道是否有可能实现。

到目前为止,我有以下内容:

平面属性文件

is.debug.mode=false

Spring XML 配置

<bean id="example"
      class="#{ ${is.debug.mode} ?
                    com.springtest.ExampleDebug :
                    com.springtest.ExampleProd}"
/>

Spring 引导 Java 代码

    // Get basic ApplicationContext - DO NOT REFRESH
    FileSystemXmlApplicationContext applicationContext = new
            FileSystemXmlApplicationContext
            (new String[] {pathSpringConfig}, false);

    // Load properties
    ResourceLoader resourceLoader = new DefaultResourceLoader ();
    Resource resource = resourceLoader.getResource("file:" + pathProperties);
    Properties properties = new Properties();
    properties.load(resource.getInputStream());

    // Link to ApplicationContext
    PropertyPlaceholderConfigurer propertyConfigurer =
            new PropertyPlaceholderConfigurer()   ;
    propertyConfigurer.setProperties(properties) ;
    applicationContext.addBeanFactoryPostProcessor(propertyConfigurer);

    // Refresh - load beans
    applicationContext.refresh();

    // Done
    Example example = (Example) applicationContext.getBean("example");

错误消息(为清楚起见删除了很多空格)

Caused by: java.lang.ClassNotFoundException:
 #{ true ? com.springtest.ExampleDebug : com.springtest.ExampleProd}
    at java.net.URLClassLoader$1.run(URLClassLoader.java:366)
    at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
  . . . 

从消息中的“true”可以看出,is.debug.mode 属性已成功加载和替换。但还有其他事情出错了。它是我在 Java 中的引导序列吗?还是 XML 中的 SPeL 语法?还是其他问题?

顺便说一句,我知道新的 3.1 配置文件功能,但出于各种原因,我想通过 SPeL 执行此操作。我也意识到我正在使用基于文件系统的上下文和路径 - 我也有理由这样做。

【问题讨论】:

    标签: java spring


    【解决方案1】:

    您可以使用 factoryBean 完成您的目标:

    <bean id="example" class="MyFactoryBean">
      <property name="class" value="#{ ${is.debug.mode} ? com.springtest.ExampleDebug : com.springtest.ExampleProd}"/>
    </bean>
    

    其中 MyFactoryBean 是一个普通的 FactoryBean 实现,返回指定类的实例。

    【讨论】:

    • +1 这是另一个很好的解决方法。你是说基本上SPeL评估不会发生在&lt;bean&gt;class属性中?
    • 我认为课程不是通过 EL 处理的。我依稀记得在来源中检查过这个。
    • 我相信你检查来源的记忆。我刚刚在&lt;property value=&gt; 中使用了相同的SPeL 表达式,但在&lt;bean class=&gt; 中仍然失败。这对我来说是确认,我会同意你的作为答案。
    • 顺便说一句,我正在使用 3.1 配置文件功能作为解决方法 - 绝对值得一试,请参阅 this article
    • 谢谢,我们目前使用的是 3.0,有时间会尝试迁移。
    【解决方案2】:

    你可以这样做。

    debug.class=com.springtest.ExampleDebug
    #debug.class=com.springtest.ExampleProd
    

    然后

    <bean id="example" class="${debug.class}"/>
    

    【讨论】:

    • 这是一个很好的解决方法,我可能会求助于它。但是您确定 SpEL 在 Spring 上下文 XML 中不起作用吗? This Spring documentation 似乎表明确实如此。或者你的意思是我目前使用的ApplicationContext 的类型?谢谢。
    • 你有权利它应该工作。你有什么样的应用程序?您是否尝试过这样的表达 #{ properties['is.debug.mode'] ? .. : ..}
    • 可能属性类不支持 SpEL 评估。尝试将表达式放入某个属性。
    • 试过你建议的语法,它无法解析properties['is.debug.mode']。无论如何,我们知道它正在解析${is.debug.mode},因为来自原始帖子的错误消息显示它解析为true。关于class 是否支持 SpEL 评估,我已经做了相当多的谷歌搜索,并且看到有人建议它支持,但没有真正的工作示例。
    • 这对我不起作用。我得到 ClassNotFoundExcpetion statign 找不到类“$ {debug.class}”。因此,这似乎没有在类属性中解决。
    【解决方案3】:

    从 Spring 4.2 开始,is possible 在类属性中使用 SpEl,因此以下效果很好:

    <bean id="example" 
          class="#{T(java.lang.Boolean).parseBoolean('${is.debug.mode:false}') ?       
                  'com.springtest.ExampleDebug' :                              
                  'com.springtest.ExampleProd'}"/>
    

    在我的情况下,占位符 ${is.debug.mode:false} 不起作用,所以我明确解析它。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-10-08
      • 2018-06-09
      • 2014-01-14
      • 2011-09-29
      • 2017-07-20
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多