问题
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 @Controller
annotation and the value of my string is being evaluated as the string "${loginpage.message}"
and not what is inside my properties file.
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.
回答1:
It seems that the question has been already asked Spring 3.0.5 doesn't evaluate @Value annotation from properties
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
From @Value
javadoc :
Note that actual processing of the @Value annotation is performed by a BeanPostProcessor
From Spring documentation:
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.
回答2:
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.
回答3:
You can @Autowire Environment
and then environment.getProperty("name")
.
See https://stackoverflow.com/a/15562319/632293
回答4:
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
@Bean
public static PropertySourcesPlaceholderConfigurer propertyConfigInDev() {
return new PropertySourcesPlaceholderConfigurer();
}
Or if you are using xml based then declare the bean accordingly.
回答5:
I had similar issue in my spring project, but specifically spring BATCH one. I built initially my config as below
@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
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
...
@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').
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.
Hope this spring batch case can be helpful for someone!
来源:https://stackoverflow.com/questions/11890544/spring-value-annotation-in-controller-class-not-evaluating-to-value-inside-pro