1

フィールド インジェクションを使用してBeanという別のクラスに依存する というクラスがあり、これらのクラスのコードを変更できないとします。別のクラス ( ) は、いつでも Bean の新しいインスタンスを構築するために を使用します。これらのクラスのコードは自由に変更できます。ServiceAppProvider

のメソッドProviderでは、演算子get()を使用して新しいインスタンスが作成されるため、 を に注入することはできません。そのため、インスタンスは不完全になります (サービス フィールドは になります)。newServiceBeanBeannull

この問題を回避する 1 つの方法Injectorは、プロバイダーにを挿入し、新しいインスタンスでメソッドinjector.injectMembers()を呼び出すことです。get()

コードの例は次のとおりです (コードを短くするためにインターフェイスを使用することは避けました)。

class Bean {
    @Inject private Service service;

    public Bean() {
    }

    public void bar() {
        this.service.foo();
    }
}

class Service {

    public void foo() {
        System.out.println("foo");
    }
}

class App {
    @Inject private Provider<Bean> beanProvider;

    public App() {
    }

    public void run() {
        this.beanProvider.get().bar();
    }
}

class BeanProvider implements Provider<Bean> {
    @Inject Injector injector;

    public Bean get() {
        Bean mybean = new Bean();
        this.injector.injectMembers(mybean);

        return mybean;
    }
}

// A simple module to bind the classes
class MyModule extends AbstractModule {

    @Override
    protected void configure() {
        bind(Service.class);
        bind(Bean.class).toProvider(BeanProvider.class);
        bind(App.class);
    }
}


public static void main(String[] args) {
    Injector injector = Guice.createInjector(new MyModule());
    injector.getInstance(App.class).run();
}

もう 1 つの方法は、コンストラクション インジェクションを使用するように Bean を変更することですが、前述したように、それができないと仮定しましょう。

ほとんどの人Injectorは、インジェクターはアプリケーションのエントリ ポイントでのみ使用し、それ以外の場所では使用しないため、DI の哲学全体を壊すため、避けるべきだと主張していますが、Guice はアプリで DI を使用するさまざまな方法を提供しているため、フィールド インジェクションなど、私が説明したような状況が発生する可能性があります。また、いくつかのプロジェクトでフィールド インジェクションがかなり頻繁に使用されているのを見てきました。

Injectorそれで、私が説明した問題に注入するのを避けるための「よりクリーンな」方法はありますか?

4

1 に答える 1

4

これは、モジュールの問題ではないようです。プロバイダーを作成する必要はまったくないようです。

モジュールで設定したバインディングにより、必要な場所に Service が Bean に注入されます。したがって、App のプロバイダー宣言を Bean のインジェクションに置き換えることができるはずです。

class App {
     @Inject private Bean beanObject;

     public App() {
     }

     public void run() {
         this.beanObject.bar();
     }
}

// A simple module to bind the classes
class MyModule extends AbstractModule {
    @Override
    protected void configure() {
        //bind this to whatever you want to inject into Bean...
        bind(Service.class); 
        bind(Bean.class);
        bind(App.class);
    }
}

それがうまくいかない場合は、何をしようとしているのか、なぜプロバイダーが必要なのかを明確にしていただけますか?

于 2014-03-12T22:21:47.100 に答える