@Autowired Beanは、別のBeanのコンストラクターで参照されるとnullになります。


89

以下に示すのは、ApplicationProperties Beanを参照するコードスニペットです。コンストラクタから参照するとnullになりますが、別のメソッドから参照すると問題ありません。これまで、他のクラスでこのautowired Beanを使用することに問題はありませんでした。しかし、これを別のクラスのコンストラクターで使用しようとしたのはこれが初めてです。

以下のコードスニペットでは、コンストラクターから呼び出されたときにapplicationPropertiesがnullになっていますが、convertメソッドで参照された場合はnullになりません。何が欠けている

@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");
  }

回答:


179

自動配線(Dunesコメントからのリンク)は、オブジェクトの構築後に発生します。したがって、コンストラクタが完了するまで設定されません。

初期化コードを実行する必要がある場合は、コンストラクターのコードをメソッドにプルし、そのメソッドにで注釈を付けることができ@PostConstructます。


3
-それは、ドキュメントに言うようにstatic.springsource.org/spring/docs/2.5.x/api/org/...
砂丘

リンクありがとうございます。簡単に見つけられるように回答に追加します。
nicholas.hauschild 2011年

2
ありがとう、私はまだ「フィールドがBeanの構築直後に注入される...」という重要なステートメントに出くわしていませんでした。私は@PostConstructアノテーションを試しましたが、それはまさに私が必要としたものです。
hairyone

@PostConstructに関するリンク投稿することもいいだろうstatic.springsource.org/spring/docs/3.0.0.M3/reference/html/...
Timofey

@ティムありがとう!AnswersリンクをSpring 3.2バージョンに更新し、Spring 3.2バージョンのリンクも追加しました。
nicholas.hauschild

44

構築時に依存関係を挿入するには、コンストラクターに@Autowired注釈を付ける必要があります。

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

2
実際、これが望ましい答えだと思います。コンストラクタベースの依存性注入アプローチは、必須コンポーネントに非常に適しています。このアプローチを使用すると、Springフレームワークはコンポーネントへの循環依存を検出することもできます(AはBに依存し、BはCに依存し、CはAに依存するため)。セッターまたは自動配線フィールドを使用したインジェクションスタイルは、完全に初期化されていないBeanをフィールドにインジェクトして、少し面倒にすることができます。
Seakayone 2016年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.