使用SpEL表达式和PropertyPlaceHolder设置Spring bean类名

时间:2012-03-28 12:48:15

标签: java spring

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

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

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

截至此日期,在class的{​​{1}}属性中,Spring SpEL 无法执行

原始问题:

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

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

平面属性文件

PropertyPlaceHolder

Spring XML配置

is.debug.mode=false

Spring引导程序Java代码

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

错误消息(为清晰起见,删除了大量空格)

    // 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属性已成功加载并替换。但是别的东西出了问题。它是我在Java中的引导序列吗?或者XML中的SPeL语法?还是另一个问题?

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

3 个答案:

答案 0 :(得分:4)

你可以用factoryBean完成你想要的东西:

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

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

答案 1 :(得分:2)

你可以这样做。

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

然后

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

答案 2 :(得分:2)

从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}不起作用,所以我明确解析它。