web-dev-qa-db-ja.com

プロパティのSpring @ Autowiredと@Valueが機能しない

プロパティで@Valueを使用したいのですが、常に0(int)を取得します。
しかし、コンストラクターパラメーターでは機能します。

例:

@Component
public class FtpServer {

    @Value("${ftp.port}")
    private int port;

    public FtpServer(@Value("${ftp.port}") int port) {
        System.out.println(port); // 21, loaded from the application.properties.
        System.out.println(this.port); // 0???
    }
}

オブジェクトはスプリング管理されています。そうでない場合、コンストラクターパラメーターは機能しません。

この奇妙な行動の原因を誰かが知っていますか?

9
Jan Wytze

明らかにコンテナは存在しないもののプロパティを設定できないため、フィールドインジェクションはオブジェクトが構築された後に行われます。フィールドはコンストラクターで常に設定解除されます。

インジェクションされた値を出力したい(または実際の初期化を実行したい:))場合は、インジェクションプロセスの後に実行される@PostConstructアノテーションが付けられたメソッドを使用できます。

@Component
public class FtpServer {

    @Value("${ftp.port}")
    private int port;

    @PostConstruct
    public void init() {
        System.out.println(this.port);
    }

}
11

この問題は、Springの実行順序が原因で発生していると思います。

  • まず、Springはコンストラクターを呼び出して、次のようなインスタンスを作成します。

    FtpServer ftpServer=new FtpServer(<value>);

  • その後、リフレクションにより、属性が入力されます。

    code equivalent to ftpServer.setPort(<value>)

したがって、コンストラクターの実行中、属性は0のままです。これは、intのデフォルト値であるためです。

5
Pablo Lozano

これはメンバーインジェクションです:

@Value("${ftp.port}")
private int port;

コンストラクターからBeanをインスタンス化した後、どのスプリングが実行するか。したがって、springがクラスからBeanをインスタンス化しているとき、springは値を注入していません。そのため、デフォルトのint値0を取得しています。

メンバーの注入に固執したい場合に備えて、コンストラクターがSpringによって呼び出された後で、必ず変数を呼び出してください。

0
Raymond Stanley