@Autowired Bean ist null, wenn im Konstruktor einer anderen Bean darauf verwiesen wird

89

Unten sehen Sie einen Codeausschnitt, in dem ich versuche, auf meine ApplicationProperties-Bean zu verweisen. Wenn ich vom Konstruktor aus darauf verweise, ist es null, aber wenn ich von einer anderen Methode aus darauf verweise, ist es in Ordnung. Bisher hatte ich kein Problem damit, diese automatisch verdrahtete Bean in anderen Klassen zu verwenden. Dies ist jedoch das erste Mal, dass ich versucht habe, es im Konstruktor einer anderen Klasse zu verwenden.

Im folgenden Code-Snippet ist applicationProperties null, wenn es vom Konstruktor aufgerufen wird, aber wenn in der convert-Methode darauf verwiesen wird, ist dies nicht der Fall. Was vermisse ich

@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();
    ...

Unten finden Sie einen Ausschnitt aus 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");
  }
haarig
quelle

Antworten:

179

Autowiring (Link aus Dunes Kommentar) erfolgt nach der Erstellung eines Objekts. Daher werden sie erst nach Abschluss des Konstruktors festgelegt.

Wenn Sie einen Initialisierungscode ausführen müssen, sollten Sie in der Lage sein, den Code im Konstruktor in eine Methode zu ziehen und diese Methode mit zu kommentieren @PostConstruct.

nicholas.hauschild
quelle
3
Wie es in den Dokumenten heißt - static.springsource.org/spring/docs/2.5.x/api/org/…
Dunes
Vielen Dank für den Link, ich werde ihn der Antwort hinzufügen, damit er leicht gefunden werden kann.
nicholas.hauschild
2
Vielen Dank, ich musste noch auf die entscheidende Aussage stoßen "Felder werden direkt nach dem Bau einer Bohne injiziert ...". Ich habe die Annotation @PostConstruct ausprobiert und sie ist genau das, was ich brauchte.
Hairyone
Es wäre auch schön, einen Link über @PostConstruct static.springsource.org/spring/docs/3.0.0.M3/reference/html/…
Timofey
@ Tim Danke! Ich habe den Antwortlink auf die Spring 3.2-Version aktualisiert und eine Spring 3.2-Version Ihres Links hinzugefügt.
nicholas.hauschild
44

Um Abhängigkeiten zur Konstruktionszeit @Autowiredeinzufügen , muss Ihr Konstruktor wie folgt mit der Annoation markiert sein .

@Autowired
public DocumentManager(IApplicationProperties applicationProperties) {
  this.applicationProperties = applicationProperties;
  startOOServer();
}
mR_fr0g
quelle
2
Eigentlich denke ich, dass dies die bevorzugte Antwort sein sollte. Der konstruktorbasierte Ansatz der Abhängigkeitsinjektion eignet sich sehr gut für obligatorische Komponenten. Mit diesem Ansatz kann das Federgerüst auch zyklische Abhängigkeiten von den Komponenten erkennen (wie in A von B abhängt, B von C abhängt, C von A abhängt). Der Injektionsstil mit Setzern oder automatisch verdrahteten Feldern kann nicht vollständig initialisierte Beans in Ihr Feld injizieren, was die Dinge etwas chaotischer macht.
Seakayone