web-dev-qa-db-ja.com

抽象基本クラスで@autowiredを使用する

私が知っているように、field injectionは推奨されません。代わりにconstructorを使用してください。

ここで私がやろうとしているのは、基本クラスのコンストラクターで@Autowiredを使用し、すべてのサブクラスがアクセスできるようにすることです。一部のサブクラスでは、コンストラクターから@Autowiredになる特定のBeanも必要です。デモコードは次のとおりです:

基本クラス:

public abstract class Base {

    protected final MyDemoService myDemoService;

    @Autowired
    public Base(MyDemoService myDemoService) {
        this.myDemoService = myDemoService;
    }
}

継承された(サブ)クラス:

public class Sub extends Base {

    private final MySubService mySubService;

    @Autowired
    public Sub(MySubService mySubService) {
        this.mySubService = mySubService;
    }
} 

これにより、「デフォルトコンストラクターなし」エラーが発生します。
これは質問に似ています: 類似した質問と回答 ですが、ここでは機能しません。


私はしばらくこれに飛び込んできました、dependency injectionに関するこの記事を見つけました: さらに読む

私の質問にはSetter Injectionが正しい方法だと思いますか?

セッター注入:

public abstract class Base {

    protected MyDemoService myDemoService;

    @Autowired
    public void setMyDemoService(MyDemoService myDemoService) {
        this.myDemoService = myDemoService;
    }
}

私はJava Spring Bootを初めて使用するので、皆さんから専門知識のアドバイスを受けたいと思っています。どんな議論も大歓迎です!

14
Vigor

あなたが提供するコードはコンパイルされません。基本クラスにデフォルトのコンストラクタがない限り、子でsuper(MyDemoService)を呼び出す必要があります。

継承された(サブ)クラス:

public class Sub extends Base {

    private final MySubService mySubService;

    @Autowired
    public Sub(MySubService mySubService, MyDemoService myDemoService){
        super(myDemoService);
        this.mySubService = mySubService;
    }
} 

または、MySubServiceMyDemoServiceの実装である場合

@Autowired
public Sub(MySubService mySubService){
    super(mySubService);
}

抽象クラスのフィールドMyDemoService myDemoServiceprotectedである限り、サブクラスで使用できます。

MyDemoServiceを複数実装している場合は、 説明した回答 の説明に従って@Qualifierを使用する必要があります。

public Sub(@Qualifier("MySubService") MyDemoService mySubService){
    super(mySubService);
}
6
Sergii Bishyr

フィールドインジェクションは使用せず、必要に応じてスーパーコンストラクターにコールバックするコンストラクターインジェクションを使用してください。

コンストラクター注入は、インスタンス化の前にオブジェクトが適切に入力されることを保証しますが、セッター注入はそうではなく、コードをよりバグが発生しやすくします(別のnullポインターのバグではありません...)。

記述する必要がある追加のコードが心配な場合は、Project Lombokを使用して、Lombokにコンストラクターコードを生成させます フィールドインジェクションが悪である理由

ちなみに、Spring 4の時点では、クラスにコンストラクターが1つしかない場合、コンストラクターに@Autowiredは必要ありません。

3
PaulNUK

@Configurationクラスの使用をお勧めします。これにより、Springアノテーションをビジネスクラスから完全に削除できます。

public class Sub extends Base {

    private final MySubService mySubService;

    public Sub(MySubService mySubService, MyDemoService myDemoService){
        super(myDemoService);
        this.mySubService = mySubService;
    }
} 

春の構成:

@Configuration
public class SubConfig{

    @Bean
    public Sub sub(MySubService subService, MyDemoService demoService){
        return new Sub(subService, demoService);
    }
}

構成クラスを使用すると、魔法のクラスパススキャンに依存することはなくなりますが、実際にはBeanを手動で再度インスタンス化します。このアプローチでは、それほど驚きはありません。

2

できます!!!!コンストラクターAutowired修飾子の継承注入

基本抽象クラスDocumentoBase。

@Qualifier("DocumentServiceBase")
private DocumentService documentService;

@Autowired
public DocumentoBase(@Qualifier("DocumentServiceBase") DocumentService documentService){
    this.documentService = documentService;
}

継承クラスDocumentoController。

@Qualifier("DocumentServiceImplv13")
private DocumentService documentService;

@Autowired
public DocumentoController(@Qualifier("DocumentServiceImplv13") DocumentService documentService){
    super(documentService);
    this.documentService = documentService;
}