【问题标题】:Why can't @Value inject a JNDI value from the Environment?为什么@Value 不能从环境中注入 JNDI 值?
【发布时间】:2014-07-31 13:58:38
【问题描述】:

我在使用 @Value 注释将 JNDI 值从我的 Tomcat 注入到 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- 我已尝试简化问题,因此如果其中一个应该有效,请告诉我,因为我可能在发帖时出错了。

【问题讨论】:

标签: spring tomcat jndi


【解决方案1】:

如果你使用的是 Spring 4,你应该改变

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

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

试试看会发生什么。

【讨论】:

  • @Value("#{environment.USER_NAME}") 为我工作,而 @Value("${USER_NAME}") 没有。我实际使用的类型是URI@Value("${USER_NAME}") 我从URI 构造函数中得到一个异常,即“$”是一个无效字符,这表明它在使用$ 时采用了文字值。跨度>
  • 当使用 ${…} 占位符时,您必须注册 PropertySourcesPlaceholderConfiguere 否则它将不起作用。此注册必须使用带有@Bean 注释的public static 方法完成。请参阅此问题的已接受答案stackoverflow.com/questions/15395123/…
【解决方案2】:

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

所以我的代码看起来像:

@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 的内容(即“假设您已注册PropertySourcesPlaceHolderConfigurer”)到该问题,这意味着我们缺少配置的PropertySourcesPlaceHolderConfigurer

【讨论】:

    【解决方案3】:

    这是正确的语法

      @Value("${PASSWORD}")
    

    看看这个例子:

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

    【讨论】:

    • 但它不是来自属性文件,而是来自我容器的 context.xml 的 JNDI 值并且我已经尝试过了,但它没有用。
    【解决方案4】:

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

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

    但您还需要在static 方法中定义PropertySourcesPlaceholderConfigurer 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 的属性值在与其他属性源发生冲突的情况下优先,这可能需要也可能不需要,在这种情况下可以使用其他方法,例如 addLast() 等。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-10-27
      • 1970-01-01
      • 2017-01-23
      • 1970-01-01
      • 1970-01-01
      • 2011-02-09
      相关资源
      最近更新 更多