JavaのDIコンテナは言語機能の補完でありinjectはimport

というブログを書こうとしたら、すでにあった。
Dependency Injectionでやりたいことはモジュールimport - きしだのHatena

依存性の注入って要するにimportなので。

まず、DIコンテナを実装してみるとどういうものかがわかりやすくなります。
このときの結論はこんな感じ。

DIコンテナというのは、Javaのリフレクションやバイトコード操作、ThreadLocalといった、あまり美しくない部分を覆い隠してきれいなコードでアプリケーションを構築するための仕組み
作って理解するDIコンテナ - きしだのHatena

言語機能の補完なので、他の言語で同様に便利とは限らないわけですね。
わかりやすい例として、DIコンテナの現実的に便利なのはAOPを利用した宣言的トランザクションやログです。これはAspectJのように言語機能としてAOPが用意されていれば不要になります。

あと、これらのブログで書いてないこととしては、DIでのクラス設計というのはオブジェクト指向は関係ないってことですね。
クラス分けを恣意的に行えるので、単に作業性の問題です。

たとえば次のようなコントローラクラスがあるとします。

@Path("/home")
@RestController
public class HomeController {
  @Path("/hello")
  public String hello() {
    return "hello";
  }
  @Path("/info")
  public String info() {
    return "test app";
  }
}

このようなクラスでメソッドが多くなったときなどに、次のように2つのクラスに分割することは簡単です。

@Path("/")
@RestController
public class HelloController {
  @Path("/home/hello")
  public String hello() {
    return "hello";
  }
}
@Path("/")
@RestController
public class InfoController {
  @Path("/home/info")
  public String info() {
    return "test app";
  }
}

逆に、コードの整理でメソッドが少なくなったり、必要と思ったらそれほどメソッドは必要なかったりで、メソッドが少なすぎる複数のクラスを統合することもあります。

単にどのメソッドをひとつのファイルにまとめておくと便利かという観点でクラスを定義することになりますね。グループ分けの問題であり線引きの問題です。

これがたとえば、ListのメソッドをMapにもっていくとか、ArrayListとLinkedListを統合しようとかいったことは簡単ではありません。そもそもとして「やろうとしたらできるかもしれないけどやるべきじゃないんでは?」となりますね。

ということで、DIでのインスタンスメソッドはAOPなどいろいろ仕込みたいときにstaticだと難しいので仕組み的にインスタンスメソッドを利用しているだけだし、そうするとimportが行えないので@Injectしている、というふうに考えるほうが利用しやすくなると思います。