@Controller 类中的 Spring @Value 注释不评估属性文件中的值

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/11890544/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-08 05:18:20  来源:igfitidea点击:

Spring @Value annotation in @Controller class not evaluating to value inside properties file

springproperties

提问by Chris

I am new to Spring and trying to inject a string with a value using the @Value("${loginpage.message}")annotation inside of a controller annotated with the @Controllerannotation and the value of my string is being evaluated as the string "${loginpage.message}"and not what is inside my properties file.

我是 Spring 的新手,并尝试使用带有@Value("${loginpage.message}")注释的控制器内部的注释注入一个带有值的字符串,@Controller并且我的字符串的值被评估为字符串,"${loginpage.message}"而不是我的属性文件中的内容。

Below is my controller with the string 'message' that I want to inject.

下面是我的控制器,其中包含我要注入的字符串“消息”。

@Controller
public class LoginController extends BaseController {
    @Value("${loginpage.message}")
    private String message;

    @RequestMapping("/")
    public String goToLoginPage(Model model) {
        model.addAttribute("message", message);

        return "/login";
    }
}

My application context looks like this:

我的应用程序上下文如下所示:

<context:property-placeholder location="classpath:properties/application.properties" />

<context:annotation-config />

<context:component-scan base-package="com.me.application" />

My properties file has the line:

我的属性文件有一行:

loginpage.message=this is a test message

Spring must be picking up the value at some point because whenever I change @Value("${loginpage.message}")to a value not in the properties file like @Value("${notInPropertiesFile}"), I get an exception.

Spring 必须在某个时候获取该值,因为每当我更改@Value("${loginpage.message}")为不在属性文件中的值时,例如@Value("${notInPropertiesFile}"),我都会收到异常。

回答by Boris Treukhov

It seems that the question has been already asked Spring 3.0.5 doesn't evaluate @Value annotation from properties

似乎已经问过这个问题Spring 3.0.5 没有从属性中评估 @Value 注释

The difference between web app root and servlet application contexts is one of the top sources of confusion in Spring, see Difference between applicationContext.xml and spring-servlet.xml in Spring Framework

Web 应用程序根和 servlet 应用程序上下文之间的差异是 Spring 中最容易混淆的来源之一,请参阅 Spring Framework 中 applicationContext.xml 和 spring-servlet.xml 之间的差异

From @Valuejavadoc :

@Valuejavadoc :

Note that actual processing of the @Value annotation is performed by a BeanPostProcessor

注意@Value注解的实际处理是由一个BeanPostProcessor执行的

From Spring documentation:

来自Spring 文档:

BeanPostProcessor interfaces are scoped per-container. This is only relevant if you are using container hierarchies. If you define a BeanPostProcessor in one container, it will only do its work on the beans in that container. Beans that are defined in one container are not post-processed by a BeanPostProcessor in another container, even if both containers are part of the same hierarchy.

BeanPostProcessor 接口的范围是每个容器的。这仅在您使用容器层次结构时才相关。如果你在一个容器中定义了一个 BeanPostProcessor,它只会在那个容器中的 bean 上工作。在一个容器中定义的 Bean 不会由另一个容器中的 BeanPostProcessor 进行后处理,即使两个容器都是同一层次结构的一部分。

回答by tn.stackoverflow

Yea I am having same issue with Spring 3. It doesn't seem to work inside Controllers. To fix the issue I created a another bean with @Service and injected that into the controller. It did work for me. Hope this would be helpful to someone as I spent all day to figure it out.

是的,我在 Spring 3 中遇到了同样的问题。它似乎在控制器中不起作用。为了解决这个问题,我用@Service 创建了另一个 bean 并将其注入控制器。它确实对我有用。希望这会对某人有所帮助,因为我花了一整天的时间来弄清楚。

回答by jediz

You can @Autowire Environmentand then environment.getProperty("name"). See https://stackoverflow.com/a/15562319/632293

你可以@Autowire Environment然后environment.getProperty("name")。见https://stackoverflow.com/a/15562319/632293

回答by AbdusSalam

You need to use PropertySourcePlaceHolder if you are using @Value annotation because it can extract the value from a properties file. If you are using java config base you need to create a bean like this

如果您使用 @Value 注释,则需要使用 PropertySourcePlaceHolder,因为它可以从属性文件中提取值。如果您使用的是 java config base,则需要像这样创建一个 bean

@Bean
public static PropertySourcesPlaceholderConfigurer propertyConfigInDev() {
    return new PropertySourcesPlaceholderConfigurer();
}

Or if you are using xml based then declare the bean accordingly.

或者,如果您使用的是基于 xml 的,则相应地声明 bean。

回答by Stefano Scarpanti

I had similar issue in my spring project, but specifically spring BATCH one. I built initially my config as below

我在 spring 项目中遇到了类似的问题,但特别是 spring BATCH one。我最初构建我的配置如下

@Configuration
public class BatchConfig   
{
  @Bean
  public Job job(@Autowired Step stepMulti, @Autowired Step stepMultiDiff,  @Autowired Step stepMultiPolling
        ){

    Job job = jobBuilders.get("job")
                .start(init0())
                    .on("POLLING").to(stepMultiPolling)
                .from(init0()).on("*").to(stepMulti).next(stepMultiDiff).end()
                .build();
    return job;
  }

  @Bean
  public Step init0(){
    return stepBuilders.get("init0")
            .tasklet(new MyDecider())
            .build();
  }

  ...
}

with MyDecider shortly as below

与 MyDecider 简单如下

public class MyDecider implements StepExecutionListener , Tasklet{ 

  @Autowired ThreadPoolTaskScheduler taskScheduler;
  @Value("${read.chunk.size}") private Integer pagesize;

@Override
public RepeatStatus execute(StepContribution stepContribution, ChunkContext chunkContext) throws Exception {
    return RepeatStatus.FINISHED;
}

@Override
public ExitStatus afterStep(StepExecution exe) {
    String type = exe.getJobParameters().getString("mode");

    log.info("SPRING BATCH props:");
    log.info("    READ chunk size:  {}", pagesize);


    if (StringUtils.equals(type, "send")) {
        log.info("MODE batch SENDING...");

        if (taskScheduler !=null) taskScheduler.shutdown();
        else log.info("      Not able to stop scheduler (is null)");

        return new ExitStatus("SEND");
    } else  {
        log.info("MODE batch POLLING...");
        return new ExitStatus("POLLING");
    } 

}

But in this way neither taskScheduler was wired nor pagesize was injected; both null. Thanks to Boris answer, after some try, I changed BatchConfig as below perfectly working

但是这样既没有连接 taskScheduler 也没有注入 pagesize;都为空。感谢鲍里斯的回答,经过一些尝试,我将 BatchConfig 更改为如下完美工作

...

@Bean
public Step init0(){
    return stepBuilders.get("init0")
            .tasklet(decider())
            .build();
}

@Bean
public Tasklet decider() {
    return new MyDecider();
}

...

Reason: having MyDecider construction closer to a Bean annotation in BatchConfig (the one of decider()), make spring understand that MyDecider has to be injected properly, with values found in application.property values, and wired with TaskScheduler used (because I tried also to have SpringScheduler activation, but I wanted to swith it off if jar starting option was 'send').

原因:让 MyDecider 构造更接近 BatchConfig 中的 Bean 注释(decider() 之一),让 spring 明白必须正确注入 MyDecider,在 application.property 值中找到值,并使用 TaskScheduler 连接(因为我试过也有 SpringScheduler 激活,但如果 jar 启动选项是“发送”,我想关闭它)。

NOTE: with option mode="send" spring batch job takes the way towards stepMulti and not stepMultiPolling, because MyDecider exit status was SEND and not POLLING; but that is just an explanation out of this topic, so I skip further details.

注意:使用选项 mode="send" spring 批处理作业采用 stepMulti 而不是 stepMultiPolling,因为 MyDecider 退出状态是 SEND 而不是 POLLING;但这只是本主题的一个解释,所以我跳过更多细节。

Hope this spring batch case can be helpful for someone!

希望这个春季批次案例可以对某人有所帮助!