@ Значение не работает внутри класса, который расширяет другие

1

Можно ли использовать @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>
  • 0
    Будьте внимательны, @Controller - это @Component . В итоге вы получите два компонента ( Lo_Controller и Lo_DisplayHandler ). Тем не менее внедрение зависимостей должно работать ... так что тут не поможет.
  • 0
    Как вы проверить , что lastPageUrl поле Lo_DisplayHandler боба null ?
Показать ещё 1 комментарий
Теги:
spring
spring-mvc

1 ответ

0
Лучший ответ

Три возможные проблемы:

Во-первых, я разочаровываюсь в расширении классов, поскольку 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();
  • 0
    LionH, я думаю, что вы дали мне очень полезную информацию, когда вы касаетесь жизненного цикла, но мне все еще нужна помощь: пожалуйста, посмотрите обновленный код из моего вопроса. Как я могу получить значение внутри anyOtherMethod? Более того, я не понимаю вашу рекомендацию «внедрить зависимость bean-компонента, определенного на корневом уровне». Что вы подразумеваете под корневым уровнем? Глядя на мой код, вы можете сказать мне, находится ли lastPageUrl в applicationContext? Если да, то какие изменения мне нужно сделать, чтобы получить к нему доступ из контекста dispatcherServelet?
  • 0
    LionH, большое спасибо за ваши комментарии. Я думаю, мне нужно больше изучать контекст и жизненный цикл, но определенно ваши идеи были полезны.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню