为什么@Value不能从环境中注入JNDI值?

时间:2014-06-10 17:19:53

标签: spring tomcat jndi

我在使用@Value注释将Tomcat中的JNDI值注入spring java配置时遇到问题,而我通过Environment类检索值并没有遇到任何问题。我们使用的是Java 1.7.0_17,Spring 4.0.3和Tomcat 7.0.52。

我在context.xml中定义了以下变量:

<Environment name="USER_NAME" value="initech" type="java.lang.String" />
<Environment name="USER_PASSWORD" value="1n3+3ch!" type="java.lang.String" />

在我的Java配置文件中,我有以下代码 正常工作

@Bean
public Foo foo( Environment env ){
    return new Foo( env.getProperty("USER_NAME"), env.getProperty("USER_PASSWORD") );
}

当我查看服务器日志时,我看到:

12:50:45.214 [RMI TCP Connection(3)-127.0.0.1] DEBUG o.s.c.e.PropertySourcesPropertyResolver -> Searching for key 'USER_NAME' in [servletConfigInitParams]
12:50:45.214 [RMI TCP Connection(3)-127.0.0.1] DEBUG o.s.c.e.PropertySourcesPropertyResolver -> Searching for key 'USER_NAME' in [servletContextInitParams]
12:50:45.214 [RMI TCP Connection(3)-127.0.0.1] DEBUG o.s.c.e.PropertySourcesPropertyResolver -> Searching for key 'USER_NAME' in [jndiProperties]
12:50:45.214 [RMI TCP Connection(3)-127.0.0.1] DEBUG o.springframework.jndi.JndiTemplate -> Looking up JNDI object with name [java:comp/env/USER_NAME]
12:50:45.214 [RMI TCP Connection(3)-127.0.0.1] DEBUG o.s.jndi.JndiLocatorDelegate -> Located object with JNDI name [java:comp/env/USER_NAME]
12:50:45.214 [RMI TCP Connection(3)-127.0.0.1] DEBUG o.s.jndi.JndiPropertySource -> JNDI lookup for name [USER_NAME] returned: [initech]
12:50:45.214 [RMI TCP Connection(3)-127.0.0.1] DEBUG o.s.c.e.PropertySourcesPropertyResolver -> Found key 'USER_NAME' in [jndiProperties] with type [String] and value 'initech'

但是,如果可能的话,我想使用@Value注释来使代码更清晰;

的内容
@Bean
public Foo foo(
        @Value( "#{USER_NAME}" ) String userName,
        @Value( "#{USER_PASSWORD}" ) String userPassword
    ){

    return new Foo( userName, userPassword );
}

但此代码会导致错误:

nested exception is org.springframework.expression.spel.SpelEvaluationException: EL1008E:(pos 0): Property or field 'USER_NAME' cannot be found on object of type 'org.springframework.beans.factory.config.BeanExpressionContext' - maybe not public?; nested exception is org.springframework.beans.factory.BeanExpressionException: Expression parsing failed; nested exception is org.springframework.expression.spel.SpelEvaluationException: EL1008E:(pos 0): Property or field 'USER_NAME' cannot be found on object of type 'org.springframework.beans.factory.config.BeanExpressionContext' - maybe not public?; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'oauthTokenRequestClient' defined in class path resource [com/initech/set/gw/api/config/GatewayRepositoryConfig.class]: Unsatisfied dependency expressed through constructor argument with index 0 of type [java.net.URI]: : Expression parsing failed; nested exception is org.springframework.expression.spel.SpelEvaluationException: EL1008E:(pos 0): Property or field 'USER_NAME' cannot be found on object of type 'org.springframework.beans.factory.config.BeanExpressionContext' - maybe not public?; nested exception is org.springframework.beans.factory.BeanExpressionException: Expression parsing failed; nested exception is org.springframework.expression.spel.SpelEvaluationException: EL1008E:(pos 0): Property or field 'USER_NAME' cannot be found on object of type 'org.springframework.beans.factory.config.BeanExpressionContext' - maybe not public?
org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:747)
org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:462)

我也尝试了"#{systemEnvironment.USER_NAME}"#{systemProperties.USER_NAME}"#{jndiProperties.USER_NAME}"#{java:comp/env/USER_NAME}:但是,它们都没有效果。

PS-我试图简化这个问题,所以如果其中一个应该工作,请告诉我,因为我的帖子可能有误。

4 个答案:

答案 0 :(得分:6)

我使用问题the selected answer中的Java Spring: How to use @Value annotation to inject an Environment property?解决了问题。

所以我的代码如下:

@Bean
public Foo foo(
        @Value( "#{environment.USER_NAME}" ) String userName,
        @Value( "#{environment.USER_PASSWORD}" ) String userPassword
    ){

    return new Foo( userName, userPassword );
}

我假设the most upvoted answer的内容(即&#34;假设您有PropertySourcesPlaceHolderConfigurer已注册&#34;)该问题,这意味着我们缺少配置PropertySourcesPlaceHolderConfigurer

答案 1 :(得分:1)

如果您使用的是Spring 4,则应更改

  @Value( "#{USER_PASSWORD}" ) String userPassword

@Value( "${USER_PASSWORD}" ) String userPassword

试试看看会发生什么。

答案 2 :(得分:1)

对于Spring 3.1+(在4.2.5.RELEASE上测试),您可以像这样使用@Value

@Value("${property.name}")
private String jndiProperty;

但是您还需要在PropertySourcesPlaceholderConfigurer方法中定义static bean 配置JndiPropertySource(我在@Configuration中有这个类):

@Bean
public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer(ConfigurableEnvironment env) {
    PropertySourcesPlaceholderConfigurer placeholderConfigurer = new PropertySourcesPlaceholderConfigurer();

    JndiPropertySource jndiPropertySource = new JndiPropertySource("java:comp");
    env.getPropertySources().addFirst(jndiPropertySource);

    return placeholderConfigurer;
}

注意使用addFirst()确保来自JNDI的属性值优先于与其他属性源发生冲突的情况,这可能是也可能不需要,在这种情况下,可以使用其他方法,如{{1}等等。

答案 3 :(得分:-2)

这是正确的syntex

  @Value("${PASSWORD}")

看一下这个例子:

http://www.programsji.com/spring/readpropertyfile