Можно ли использовать @Value
внутри класса, который расширяет другой класс?
Ниже приведены соответствующие фрагменты кода. В классе Lo_Controller
он работает отлично, но в Lo_DisplayHandler
всегда возвращает null
. Единственная причина, по которой я могу думать, это потому, что она зависит от другого класса, который не аннотируется с @Component
. Если это причина, то какой рекомендуемый параметр для чтения значения из файла свойств, аналогичного @Value
?
Чтобы проверить это, я изменил с @Component
на @Controller
в Lo_DisplayHandler
чтобы увидеть, если они каким-то образом связаны друг с другом, однако он также возвращает null
.
Это работает:
package com.ma.common.controller;
imports ...
@Controller
@RequestMapping("/log")
public class Lo_Controller {
@Value("${log.display.lastpage}")
private String lastPageUrl;
...
Это всегда возвращает null
:
package com.ma.log.handler;
imports ...
@Component
public class Lo_DisplayHandler extends Lo_Handler {
public Lo_DisplayHandler() {
super();
}
@Value("${log.display.lastpage}")
private String lastPageUrl;
...
MVC-диспетчерская-servlet.xml
<context:component-scan base-package="com.ma.common.controller, com.ma.log.handler" />
<context:property-placeholder location="classpath:restServices.properties"/>
<mvc:annotation-driven />
<mvc:resources mapping="/**" location="/" />
@Component
public class Lo_DisplayHandler extends Lo_Handler {
@Value("${log.display.lastpage}")
private String lastPageUrl;
public void anyOtherMethod(){
String _a = lastPageUrl; //FAIL - always null
}
@PostConstruct
public void initIt() throws Exception {
String _a = lastPageUrl; //OK - when the application is deployed and started for the first time
}
@PreDestroy
public void cleanUp() throws Exception {
String _a = lastPageUrl; //OK - when the application is stopped
}
web.xml
<servlet>
<servlet-name>mvc-dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>mvc-dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/mvc-dispatcher-servlet.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
Три возможные проблемы:
Во-первых, я разочаровываюсь в расширении классов, поскольку Spring работает лучше, чем autowiring зависимости. Но это должно работать во-вторых, вам нужно сосредоточиться на жизненном цикле компонента. Имущество будет установлено после введения. @PostConstruct для проверки содержимого. В-третьих, видимость в иерархическом контексте владельца собственности не является прямой. Поэтому, если вы определяете @value в корневом приложении ApplicationContext, он не будет установлен в контексте вашего диспетчераServlet. Чтобы протестировать его, пожалуйста, вставьте зависимость компонента, определенного на корневом уровне, вы увидите, что ваш @Value будет принимать во внимание.
Свойство lastPageUrl будет доступно из компонента в том же контексте (путем создания push или создания pull). В случае создания push, если другой bean autowire Lo_DisplayHandler bean и вызовите ваш метод anyOtherMethod(), он получит значение.
@Component
public class ScannableIntoYourContext{
@Autowired
private Lo_DisplayHandler myHandler;
}
Другой способ - вытащить компонент из ObjectFactory.
@Autowired
private ObjectFactory<Lo_DisplayHandler> bean;
Lo_DisplayHandler instanceFromContext = bean.getObject();
@Controller
- это@Component
. В итоге вы получите два компонента (Lo_Controller
иLo_DisplayHandler
). Тем не менее внедрение зависимостей должно работать ... так что тут не поможет.lastPageUrl
полеLo_DisplayHandler
бобаnull
?