DIフレームワーク Zenject と Spring を比べてみた
最近、Unity のDIフレームワーク Zenject に触れる機会がありました。過去に業務で、Java の DIフレームワーク Spring (厳密にはWeb開発向けの Spring Boot )を利用したことがあるので、その比較をしてみたいと思います。
DIとは何か?については、過去にこんな記事を書いたので、興味があればご覧ください。
肥満な物語でDIを解説する
フィールドインジェクション
クラスのフィールドに注入の設定を記載することをフィールドインジェクションと呼びます。Zenjectでは [Inject]
、Spring では @Autowired
を使います。記述方法がかなり似ていますね。
public class Sample
{
[Inject]
private Foo _foo;
[Inject]
private Bar _bar;
}
@Component
public class Sample {
@Autowired
private Foo _foo;
@Autowired
private Bar _bar;
}
コンストラクタインジェクション
コンストラクタインジェクションについては、特に違いはありませんでした。
public class Sample
{
private Foo _foo;
private Bar _bar;
public Sample(Foo foo, Bar bar)
{
_foo = foo;
_bar = bar;
}
}
public class Sample {
private Foo _foo;
private Bar _bar;
public Sample(Foo foo, Bar bar) {
_foo = foo;
_bar = bar;
}
}
Spring界隈では、フィールドインジェクションはなるべく使わずに、コンストラクタインジェクションを積極的に利用しよう!という声が多い気がしますが、Zenject界隈では特にそういう声はきかない気がします。
シングルトン
インスタンスをコンテナに対して1つだけ作ることを、Springではシングルトンと呼びます。
Zenjectでは AsSingle()
というメソッドがあります。
public class HogeInstaller : MonoInstaller
{
public override void InstallBindings()
{
Container.Bind<Sample>().AsSingle();
}
}
Springでは、 @Scope("singleton")
というアノテーションを利用します。
@Configuration
public class AppConfig {
@Bean
@Scope("singleton")
public Sample sample(){
return new Sample();
}
}
ただ、Springの場合、デフォルトでシングルトンなので、実は、 @Scope("singleton")
は省略可能です。
トランシェント / プロトタイプ
インスタンスを再利用せずに、注入要求があるたびに、別々のインスタンスを生成することを、Springではプロトタイプと呼び、Zenjectではトランシェントと呼ぶようです。
Zenjectでは AsTransient()
を利用します。
public class HogeInstaller : MonoInstaller
{
public override void InstallBindings()
{
Container.Bind<Sample>().AsTransient();
}
}
Springでは、 @Scope("prototype")
を利用します。
@Configuration
public class AppConfig {
@Bean
@Scope("prototype")
public Sample sample(){
return new Sample();
}
}
さいごに
C#とJavaが似ているからかもしれませんが、Zenject と Spring はかなり似ているなぁと思いました。
SpringはWebバックエンド開発、Zenjectはゲームシステム開発と、利用シーンが全然違いますが、そのどちらでも利用されるDIというアーキテクチャは本当にすごいなぁと改めて思いました。