フィールドインジェクションは、私にとっては「遠距離での不気味なアクション」です。
Googleグループの投稿で提供した例を考えてみましょう。
public class VeracodeServiceImplTest {
@Tested(fullyInitialized=true)
VeracodeServiceImpl veracodeService;
@Tested(fullyInitialized=true, availableDuringSetup=true)
VeracodeRepositoryImpl veracodeRepository;
@Injectable private ResultsAPIWrapper resultsApiWrapper;
@Injectable private AdminAPIWrapper adminApiWrapper;
@Injectable private UploadAPIWrapper uploadApiWrapper;
@Injectable private MitigationAPIWrapper mitigationApiWrapper;
static { VeracodeRepositoryImpl.class.getName(); }
...
}
つまり、基本的にあなたが言っているのは、「私はこのクラスにプライベート状態があり、それに@injectable
注釈を付けています。つまり、私の状態はすべてプライベートであると宣言されていても、外部から何らかのエージェントによって自動的に状態が設定されます」
私はこれの動機を理解しています。クラスを適切に設定することに固有の式典の多くを回避する試みです。基本的に、「ボイラープレートをすべて書くのにうんざりしているので、すべての状態に注釈を付けて、DIコンテナに設定してもらいます」ということです。
それは完全に有効な視点です。しかし、これはおそらく回避すべきでない言語機能の回避策でもあります。また、なぜそこで停止するのですか?従来、DIは、コンパニオンインターフェイスを持つ各クラスに依存していました。アノテーションを使用してこれらのインターフェースもすべて削除しないのはなぜですか?
代替案を検討してください(これはC#になります。これは私がよく知っているためですが、Javaにはおそらく完全に同等のものがあります)。
public class VeracodeService
{
private readonly IResultsAPIWrapper _resultsApiWrapper;
private readonly IAdminAPIWrapper _adminApiWrapper;
private readonly IUploadAPIWrapper _uploadApiWrapper;
private readonly IMitigationAPIWrapper _mitigationApiWrapper;
// Constructor
public VeracodeService(IResultsAPIWrapper resultsApiWrapper, IAdminAPIWrapper adminApiWrapper, IUploadAPIWrapper uploadApiWrapper, IMitigationAPIWrapper mitigationApiWrapper)
{
_resultsAPIWrapper = resultsAPIWrapper;
_adminAPIWrapper = adminAPIWrapper;
_uploadAPIWrapper = uploadAPIWrapper;
_mitigationAPIWrapper = mitigationAPIWrapper;
}
}
すでにこのクラスについていくつかのことを知っています。これは不変のクラスです。状態は、コンストラクター(この特定のケースでは参照)でのみ設定できます。そして、すべてがインターフェースから派生しているため、コンストラクターで実装を交換できます。ここで、モックが入ります。
これで、DIコンテナーが行う必要があるのは、コンストラクターを反映して、更新する必要のあるオブジェクトを判別することだけです。しかし、その反映は、一流の方法で、公開メンバーに対して行われています。つまり、メタデータは既にクラスの一部であり、コンストラクタで宣言されており、その目的はクラスに必要な依存関係を提供することです。
これは定型的なものですが、これが言語の設計方法です。アノテーションは、言語自体に組み込まれるべきものに対する汚いハックのようです。