1前書き

この簡単なチュートリアルでは、

@ Lookup

アノテーションを通して、Springのメソッドレベルの依存性注入サポートを見ていきます。


2なぜ

@ Lookup




@ Lookup

のアノテーションが付けられたメソッドは、Springがそれを呼び出したときにそのメソッドの戻り型のインスタンスを返すように指示します

基本的に、Springはアノテーション付きメソッドをオーバーライドし、メソッドの戻り値の型とパラメータを

BeanFactory#getBean.

の引数として使用します。


@ Lookup

は次の場合に役立ちます。

プロトタイプスコープのbeanをシングルトンbeanにインジェクトする


プロバイダ


** 手続き的に依存関係を注入する


@ Lookup

は、XML要素

lookup-method

とJavaで同等のものです。


3

@ Lookup


を使う


3.1. プロトタイプスコープのBeanをシングルトンBeanに注入する

たまたまプロトタイプのSpring Beanを使用することにした場合、私たちのシングルトンのSpring BeanがこれらのプロトタイプのSpring Beanにどのようにアクセスするのかという問題にすぐに直面します。


@ Lookup

はいくつかの点でより汎用的ですが、

Provider

は確かに1つの方法です。

まず、後でシングルトンBeanに注入するプロトタイプBeanを作成しましょう。

@Component
@Scope("prototype")
public class SchoolNotification {
   //... prototype-scoped state
}

そして、

@ Lookup

を使用するシングルトンBeanを作成したとします。

@Component
public class StudentServices {

   //... member variables, etc.

    @Lookup
    public SchoolNotification getNotification() {
        return null;
    }

   //... getters and setters
}


@ Lookup

を使うと、シングルトンBeanを通じて

SchoolNotification

のインスタンスを取得できます。

@Test
public void whenLookupMethodCalled__thenNewInstanceReturned() {
   //... initialize context
    StudentServices first = this.context.getBean(StudentServices.class);
    StudentServices second = this.context.getBean(StudentServices.class);

    assertEquals(first, second);
    assertNotEquals(first.getNotification(), second.getNotification());
}


StudentServices

では、スタブとして

getNotification

メソッドを残しました。

これは、Springが

beanFactory.getBean(StudentNotification.class)

の呼び出しでこのメソッドをオーバーライドするため、空のままにできるためです。


3.2. 依存関係を手続き的に注入する

さらに強力なのは、

@ Lookup

を使用して手続き的に依存関係を注入できることです。

いくつかの状態で

StudentNotification

を強化しましょう。

@Component
@Scope("prototype")
public class SchoolNotification {
    @Autowired Grader grader;

    private String name;
    private Collection<Integer> marks;

    public SchoolNotification(String name) {
       //... set fields
    }

   //... getters and setters

    public String addMark(Integer mark) {
        this.marks.add(mark);
        return this.grader.grade(this.marks);
    }
}

さて、それは私たちが手続き的に提供することになる、いくつかのSpringのコンテキストとまた追加のコンテキストに依存しています。

それから、生徒データを取得してそれを保持するメソッドを

StudentServices

に追加できます。

public abstract class StudentServices {

    private Map<String, SchoolNotification> notes = new HashMap<>();

    @Lookup
    protected abstract SchoolNotification getNotification(String name);

    public String appendMark(String name, Integer mark) {
        SchoolNotification notification
          = notes.computeIfAbsent(name, exists -> getNotification(name)));
        return notification.addMark(mark);
    }
}

実行時に、Springはいくつかのトリックを追加して同じ方法でメソッドを実装します。

最初に、それは複雑なコンストラクタを呼び出すことができ、他のSpring Beanをインジェクトすることができるので、SchoolNotificationをSpringを意識したメソッドのように扱うことができます。

これを行うには、

beanFactory.getBean(SchoolNotification.class、name)

を呼び出して

getSchoolNotification

を実装します。

次に、上の例のように、

__ @ Lookup –

__アノテーション付きメソッドを抽象化することもできます。


abstract

を使うのはスタブより少し見栄えがいいですが、それを使うことができるのは



component-scan



@ Bean

-manage ** が周囲のbeanでない場合です。

@Test
public void whenAbstractGetterMethodInjects__thenNewInstanceReturned() {
   //... initialize context

    StudentServices services = context.getBean(StudentServices.class);
    assertEquals("PASS", services.appendMark("Alex", 89));
    assertEquals("FAIL", services.appendMark("Bethany", 78));
    assertEquals("PASS", services.appendMark("Claire", 96));
}

この設定で、Springの依存関係とメソッドの依存関係を

SchoolNotification

に追加できます。


4制限事項


@ Lookup

の汎用性にもかかわらず、注目すべきいくつかの制限があります。


  • getNotificationのような

    @ Lookup

    アノテーション付きメソッド、

    具体的でなければならない

__Studentのような周囲のクラスがコンポーネントスキャンされている場合。これは、コンポーネントスキャンが抽象Beanをスキップするためです。


  • __ @ Lookup –

    __アノテーション付きメソッドは、周囲の状況ではまったく機能しません。

クラスは

@ Bean

管理対象です。

そのような状況で、プロトタイプBeanをシングルトンに注入する必要がある場合は、代わりに

Provider

を見ることができます。


5結論

このクイック記事では、Springの

@ Lookup

アノテーションを使用する方法とタイミング(プロトタイプスコープのBeanをシングルトンBeanに注入する方法、および依存関係を手続き的に注入する方法を含む)を学びました。

このチュートリアルで使われているすべてのコードはhttps://github.com/eugenp/tutorials/tree/master/spring-core[over Github]で見つけることができます。