Kacang @Autowired adalah null saat direferensikan dalam konstruktor kacang lain

90

Di bawah ini adalah potongan kode tempat saya mencoba dan mereferensikan kacang ApplicationProperties saya. Ketika saya mereferensikannya dari konstruktor, nilainya null, tetapi ketika direferensikan dari metode lain tidak apa-apa. Sampai saat ini saya tidak memiliki masalah dalam menggunakan kacang autowired ini di kelas lain. Tapi ini pertama kalinya saya mencoba menggunakannya di konstruktor kelas lain.

Dalam potongan kode di bawah applicationProperties bernilai null saat dipanggil dari konstruktor, tetapi saat direferensikan dalam metode convert, nilainya tidak. Apa yang saya lewatkan

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

Di bawah ini adalah cuplikan dari 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");
  }
berbulu
sumber

Jawaban:

181

Autowiring (tautan dari komentar Dunes) terjadi setelah konstruksi objek. Oleh karena itu, mereka tidak akan ditetapkan sampai setelah konstruktor selesai.

Jika Anda perlu menjalankan beberapa kode inisialisasi, Anda harus dapat menarik kode dalam konstruktor ke dalam sebuah metode, dan memberi anotasi pada metode itu dengan @PostConstruct.

nicholas.hauschild
sumber
3
Seperti yang tertulis di dokumen - static.springsource.org/spring/docs/2.5.x/api/org/…
Bukit pasir
Terima kasih untuk tautannya, saya akan menambahkannya ke jawaban agar mudah ditemukan.
nicholas.hauschild
2
Terima kasih, saya belum menemukan pernyataan penting "Ladang disuntikkan tepat setelah pembuatan kacang ...". Saya telah mencoba anotasi @PostConstruct dan itulah yang saya butuhkan.
hairyone
Akan lebih baik juga untuk memposting tautan tentang @PostConstruct static.springsource.org/spring/docs/3.0.0.M3/reference/html/…
Timofey
@Tim Terima kasih! Saya memperbarui tautan jawaban ke versi Spring 3.2, dan saya juga menambahkan tautan versi Spring 3.2 Anda.
nicholas.hauschild
44

Agar dependensi diinjeksikan pada waktu konstruksi, Anda perlu memiliki konstruktor ditandai dengan @Autowiredpengumuman seperti itu.

@Autowired
public DocumentManager(IApplicationProperties applicationProperties) {
  this.applicationProperties = applicationProperties;
  startOOServer();
}
mR_fr0g
sumber
2
Sebenarnya saya pikir ini harus menjadi jawaban yang disukai. Pendekatan injeksi ketergantungan berbasis konstruktor sangat cocok untuk komponen wajib. Dengan menggunakan pendekatan ini, kerangka pegas juga akan dapat mendeteksi ketergantungan siklik pada komponen (seperti dalam A bergantung pada B, B bergantung pada C, C bergantung pada A). Gaya injeksi yang menggunakan penyetel atau bidang yang diinisialisasi secara otomatis dapat memasukkan biji yang tidak diinisialisasi sepenuhnya ke bidang Anda yang membuat segalanya sedikit lebih berantakan.
Seakayone