【问题标题】:Spring @Value annotation and setter injection differenceSpring@Value注解和setter注入区别
【发布时间】:2015-03-01 18:23:59
【问题描述】:

当我使用属性文件中的@Value 注释设置值时,它不起作用,而使用 setter 注入进行设置。

我的属性文件是这样的。

app.work.dir=file:${user.home}/WORK

类文件如下。

@Value("#{configProperties['app.work.dir']}")
private String workdir;

这是我的 xml 设置。

<util:properties id="configProperties" location="classpath:config.properties" />

当像下面这样使用 setter 注入时,它可以正常工作。

<bean id="sampleService" class="aaa.SampleService">
    <property name="workdir" value="${app.work.dir}" />
</bean>

我不确定为什么,如果可能的话,我想使用@Value 注释。

请参考下面的junit测试用例。

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:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context" xmlns:jdbc="http://www.springframework.org/schema/jdbc" xmlns:jpa="http://www.springframework.org/schema/data/jpa"
    xmlns:util="http://www.springframework.org/schema/util"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc.xsd
       http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
       http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
       http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa.xsd
       http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">

    <context:property-placeholder location="classpath:testconfig.properties" />
    <util:properties id="sampleProperties" location="classpath:testconfig.properties" />

    <bean id="exampleA" class="aa.sample.SampleA" />

    <bean id="sampleB" class="aa.sample.SampleB" >
        <property name="workdir" value="${work.dir}" />
        <property name="tempdir" value="${work.dir.test}" />
        <property name="aaa" value="${aaa}" />
    </bean>


</beans>

示例服务类:

包装 aa.sample;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

@Service
public class SampleA {

    @Value("#{sampleProperties['work.dir']}")
    private String workdir;
    @Value("#{sampleProperties['work.dir.test']}")
    private String tempdir;
    @Value("#{sampleProperties['aaa']}")
    private String aaa;

    //getter setter deleted

}

属性文件:

work.dir=file:${user.home}/WORK
work.dir.test=${work.dir}/TEST
aaa=bbb

和junit测试类:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration({ "/testcontext.xml" })
public class ExampleTest {

    @Inject
    private SampleA sampleA;

    @Inject
    private SampleB sampleB;

    @Test
    public void testValueAnnotation() {

        assertThat(sampleA.getAaa(), is("bbb"));//ok
        String tempdir = sampleA.getTempdir();
        String workdir = sampleA.getWorkdir();
        assertFalse("[sampleA] temp dir should not have ${work.dir}", tempdir.indexOf("${work.dir}") >= 0);//ng
        assertFalse("[sampleA] workdir dir should not have ${user.home}", workdir.indexOf("${user.home}") >= 0);//ng
    }


}

【问题讨论】:

  • 当使用@Value 可以获得文件:{user.home}/WORK 但使用setter 注入可以获得文件:/Users/hoge/WORK。
  • 发布您的完整配置。你有属性解析器吗?预期的结果是什么?
  • 添加完整配置请参考

标签: java spring


【解决方案1】:

生成的bean

<util:properties id="sampleProperties" location="classpath:spring.properties" />

基本上翻译成地图。这个符号

@Value("#{sampleProperties['work.dir']}")

请求使用键 work.dir 映射的其中一个值。返回的值不会发生属性解析。它是从字面上理解的。

另一方面,

<property name="tempdir" value="${work.dir.test}" />

请求一个属性,称为work.dir.test,可以递归解析。

【讨论】:

  • 感谢您的回答。你的回答意味着@Value 注解不能支持递归属性设置?
  • @rakuraku 不,它可以。使用@Value("${work.dir}"),它的行为将与您拥有的 XML 示例相同。 #{...} 表示法不进行属性解析。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-09-19
  • 2017-01-20
  • 1970-01-01
  • 2012-08-27
  • 2014-10-04
  • 2012-05-17
  • 2019-01-08
相关资源
最近更新 更多