@Autowired bean є нульовим при посиланні в конструкторі іншого bean


89

Нижче наведено фрагмент коду, де я намагаюся посилатись на мій компонент ApplicationProperties. Коли я посилаюся на нього з конструктора, він є нульовим, але при посиланні з іншого методу це нормально. Дотепер у мене не було проблем із використанням цього автопровідного боба в інших класах. Але я вперше намагався використовувати його в конструкторі іншого класу.

У фрагменті коду нижче applicationProperties має значення null при виклику з конструктора, але при посиланні в методі convert це не так. Чого мені не вистачає

@Component
public class DocumentManager implements IDocumentManager {

  private Log logger = LogFactory.getLog(this.getClass());
  private OfficeManager officeManager = null;
  private ConverterService converterService = null;

  @Autowired
  private IApplicationProperties applicationProperties;


  // If I try and use the Autowired applicationProperties bean in the constructor
  // it is null ?

  public DocumentManager() {
  startOOServer();
  }

  private void startOOServer() {
    if (applicationProperties != null) {
      if (applicationProperties.getStartOOServer()) {
        try {
          if (this.officeManager == null) {
            this.officeManager = new DefaultOfficeManagerConfiguration()
              .buildOfficeManager();
            this.officeManager.start();
            this.converterService = new ConverterService(this.officeManager);
          }
        } catch (Throwable e){
          logger.error(e);  
        }
      }
    }
  }

  public byte[] convert(byte[] inputData, String sourceExtension, String targetExtension) {
    byte[] result = null;

    startOOServer();
    ...

Нижче наведено фрагмент s із ApplicationProperties ...

@Component
public class ApplicationProperties implements IApplicationProperties {

  /* Use the appProperties bean defined in WEB-INF/applicationContext.xml
   * which in turn uses resources/server.properties
   */
  @Resource(name="appProperties")
  private Properties appProperties;

  public Boolean getStartOOServer() {
    String val = appProperties.getProperty("startOOServer", "false");
    if( val == null ) return false;
    val = val.trim();
    return val.equalsIgnoreCase("true") || val.equalsIgnoreCase("on") || val.equalsIgnoreCase("yes");
  }

Відповіді:


179

Автопровід (посилання з коментаря "Дюн") відбувається після побудови об'єкта. Тому вони будуть встановлені лише після завершення роботи конструктора.

Якщо вам потрібно запустити якийсь код ініціалізації, ви зможете витягнути код у конструкторі в метод і анотувати цей метод за допомогою @PostConstruct.


3
Як сказано в документах - static.springsource.org/spring/docs/2.5.x/api/org/…
дюни

Дякую за посилання, я додаю його до відповіді для зручності пошуку.
nicholas.hauschild

2
Дякую, я ще не стикався з вирішальним твердженням "Поля вводяться відразу після побудови квасолі ...". Я спробував анотацію @PostConstruct, і це саме те, що мені потрібно.
hairyone

також було б непогано опублікувати посилання про @PostConstruct static.springsource.org/spring/docs/3.0.0.M3/reference/html/…
Тимофій

@Tim Дякую! Я оновив посилання на відповіді до версії Spring 3.2, а також додав версію Spring 3.2 до вашого посилання.
nicholas.hauschild

44

Щоб інжектувати залежності під час побудови, потрібно, щоб ваш конструктор був позначений @Autowiredанотацією приблизно так.

@Autowired
public DocumentManager(IApplicationProperties applicationProperties) {
  this.applicationProperties = applicationProperties;
  startOOServer();
}

2
Насправді я вважаю, що це повинна бути найкраща відповідь. Підхід введення залежностей на основі конструктора дуже добре підходить для обов’язкових компонентів. Використовуючи цей підхід, пружинний каркас також зможе виявляти циклічні залежності від компонентів (як у A залежить від B, B залежить від C, C залежить від A). Стиль ін’єкції за допомогою сетерів або автопровідних полів здатний вводити не повністю ініціалізовані зерна у ваше поле, роблячи речі трохи бруднішими.
Seakayone
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.