Bean-компонент @Autowired имеет нулевое значение при ссылке в конструкторе другого bean-компонента

Ниже показан фрагмент кода, в котором я пытаюсь ссылаться на мой компонент ApplicationProperties . Когда я ссылаюсь на него из конструктора, он имеет значение null, но при обращении к нему из другого метода это нормально. До сих пор у меня не было проблем с использованием этого bean-компонента в других классах. Но я впервые попробовал использовать его в конструкторе другого класса.

В приведенном ниже фрагменте кода 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();
    ...

Ниже приведен фрагмент кода от 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");
  }

2 ответа

Решение

Автопроводка (ссылка из комментария Дюны) происходит после возведения объекта. Поэтому они не будут установлены до завершения конструктора.

Если вам нужно запустить некоторый код инициализации, вы должны иметь возможность вывести код в конструкторе в метод и аннотировать этот метод с помощью @PostConstruct,

Чтобы вводить зависимости во время построения, вам нужно пометить конструктор с помощью @Autowired аннотации вроде так.

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

Да, оба ответа верны.

Если честно, эта проблема на самом деле похожа на сообщение Почему мое поле Spring @Autowired имеет значение null?.

Основная причина ошибки может быть объяснена в справочном документе Spring ( Autowired), как показано ниже

Автоматизированные поля

Поля вводятся сразу после создания bean-компонента, до вызова каких-либо методов конфигурации.

Но настоящая причина этого утверждения в документе Spring - это жизненный цикл компонента Spring. Это часть философии дизайна Spring.

Это обзор жизненного цикла Spring Bean: Bean должен быть инициализирован, прежде чем он может быть введен с такими свойствами, как field. Так устроены бобы, вот и настоящая причина.

Надеюсь, этот ответ будет вам полезен!

Другие вопросы по тегам