LoginSignup
8
10

More than 5 years have passed since last update.

Guiceを使った動的なインジェクション

Last updated at Posted at 2014-09-18

通常のインジェクション

Google Guiceを使ったインジェクションはこんな感じになります。

Injector injector = Guice.createInjector(new AbstractModule() {
    @Override
    protected void configure() {
        bind(Logic.class).to(LogicImpl.class);
    }
});

Logic logic = injector.getInstance(Logic.class);
logic.doLogic();
...

問題点

ここのLogicImpl.classをソースに直で書いているので違う実装を使おうと思ったらソースを変更するしかありません。JUnit等でテストする場合はそれで問題ないのですが、実際の業務で使おうと思った場合はこれだと柔軟性に欠けます。

対応

ここはClass<?>を指定できればいいので外部ファイルに出してしまって Class.forName()Class<?>を得れば柔軟性が上がります。

ConfigBean config = JAXB.unmarshal(file, ConfigBean.class);

Injector injector = Guice.createInjector(new AbstractModule() {
    @Override
    protected void configure() {
        @SuppressWarnings("unchecked")
        Class<? extends Logic> cls = (Class<? extends Logic>)Class.forName(config.getLogic());
        bind(Logic.class).to(cls);
    }
});

こうすることで、

  • ファイル受信処理の骨格は共通
  • Aシステムから来たファイルはLogicAImplで処理
  • Bシステムから来たファイルはLogicBImplで処理

ということを実行時に解決させることができます。

発展

さらに、LogicAImplLogicBImplの中で使っているインタフェースも同じようにインスタンス化したい場合、だけどLogicAImplLogicBImplで使っているものが違う場合

例えば

  • LogicAImplではMasterADAO
  • LogicBImplではMasterBDAO

を使っているとすると、上記の方法だとちょっとうまくありません。不要なクラスまでインスタンス化してしまいます。

こういうときは

// インタフェース名を定義ファイルから取得
@SuppressWarnings("rawtypes")
Class intf = Class.forName(config.getInterface());

// 実装クラス名を定義ファイルから取得
@SuppressWarnings("rawtypes")
Class impl = Class.forName(config.getImplement());

bind(intf).to(impl);

こうしておきます。
Class<?>にはできないので、あえてClassを使っています。

定義ファイルにインタフェース名と実装クラス名を書いておけば、Logicをインスタンス化した場合に引きずられてインスタンス化してくれます。

定義ファイルはこんな感じで用意すればいいのではないでしょうか。

定義ファイルサンプル
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
  <file type="A">
    <logic implements="xxx.yyy.LogicAImpl">
      <with interface="xxx.yyy.dao.MasterADAO" implement="xxx.yyy.dao.impl.MasterADAOImpl" />
      <with interface="xxx.yyy.Parser" implement="xxx.yyy.util.CSVParser" />
    </logic>
  </file>
  <file type="B">
    <logic implements="xxx.yyy.LogicBImpl">
      <with interface="xxx.yyy.dao.MasterBDAO" implement="xxx.yyy.dao.impl.MasterBDAOImpl" />
    </logic>
  </file>
</configuration>

参考

8
10
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
10