Translate

2012年7月30日月曜日

Spring DIのXML設定ファイルをそのままGoogle Guiceで使う

Spring はDIが有名で
広く利用されているのだが、

[Guice] Google Guice(その5) パフォーマンス比較

とか読んでると
Google Guiceは
なんかSpring DIより速いらしいことが書かれている。


とすると使ってみたくなるのだけど、
既にSpring DIで動作させているアプリについて
設定ファイルを全部クラス化するのは面倒くさい。

なにか楽な方法はないものかと探してみたら
Google Guiceのjarに
guice-spring-3.0.jar
なるファイルが存在しているのをみつけた。

どうもSpring DIの設定ファイルを使って
Google GuiceでDIできるらしい。

ちょっとしらべてみると
その方法が意外に簡単だった。

ので、簡単なサンプルを紹介する。

ちなみに使用したライブラリは
以下のとおり。
springはもう少し整理できるかもしれない。

・apache-common-1.1
-commons-logging.jar
・guice-3.0
-aopalliance.jar
-guice-3.0.jar
-guice-spring-3.0.jar
-javax.inject.jar
・spring-3.2.0M1
-spring-aop-3.2.0M1.jar
-spring-asm-3.2.0M1.jar
-spring-beans-3.2.0M1.jar
-spring-context-3.2.0M1.jar
-spring-core-3.2.0M1.jar
-spring-expression-3.2.0M1.jar

きちんと確認していないが、
おそらくぜんぶ
Apache License 2.0だとおもう。



まずDI対象のサンプルクラス。

Product(商品)インターフェイスの
実装クラスAppleを用意する。

/**
 * sample/Product.java
 * 商品インターフェイス
 */
package sample;

public interface Product {
 public String getName();
 public int getPrice();
}


/**
 * sample/Apple.java
 * 商品実装クラスApple
 */
package sample;

public class Apple implements Product {
 private String name;
 private int price;

 @Override
 public String getName() {
  return name;
 }

 @Override
 public int getPrice() {
  return price;
 }

 public void setName(String name) {
  this.name = name;
 }

 public void setPrice(int price) {
  this.price = price;
 }

 @Override
 public String toString(){
  return "[Product]name=[" + name + "], price=[" + price + "]";
 }
}

Spring DIの設定ファイルは以下のとおり。

<!-- sample.xls -->
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

<bean id="product_apple" name="製品名:りんご" class="sample.Apple">
<property name="name" value="りんご"></property>
<property name="price" value="120"></property>
</bean>
</beans>

設定ファイル上のid値product_appleを呼び出せば
nameに"りんご"、priceに120が設定された
Appleインスタンスを得られるというだけの簡単なもの。

DIする実装は以下の様に記述する。

/**
 * sample/SampleMain.java
 * Spring設定ファイルでGuice DIを動かすサンプル
 */
package sample;

import org.springframework.beans.factory.BeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.google.inject.AbstractModule;
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.spring.SpringIntegration;

public class SampleMain {

public static void main(String[] args) {
final ApplicationContext context =
new ClassPathXmlApplicationContext("sample.xml");
Injector injector =
Guice.createInjector(new AbstractModule(){
@Override
protected void configure() {
bind(BeanFactory.class).toInstance(context);
bind(Product.class).toProvider(
SpringIntegration.fromSpring(Apple.class,"product_apple"));
    }
                   
});

Product product = injector.getInstance(Product.class);
System.out.println(product);
}
}




#設定ファイルsample.xmlの指定している箇所は
#実行する環境でパスを調整すること

SpringのApplicationContextを
GuiceのAbstractModule実装に渡して
SpringIntegrationをつかってバインドする。



そうか、BeanFactoryとしてApplicationContextをDI対象にして
よびだされたらApplicationContext#getBean()してるだけなんじゃあ...


うーん、もしそうだとしたらGuiceがかぶさってる分だけ
おそくなるんじゃないだろうか..


で、
上記サンプルのInjector#getInstance()部分をApplicationContext#getbean()にして
System.currentTimeMills()つかって計測してみたら..


種類経過時間
Springのみ466ミリ秒
Spring-Guice連携778ミリ秒


あれ?おそくなってるじゃん..



サンプルでは1回だけしかインスタンス取得してないけど
Singletonだったらたぶん2回目以降は同じくらいの速度になりそう..



とすると..
速度向上のためだけに
SpringからGuideへスイッチする場合
guice-spring-3.0.jarつかった方法ではなく
きちんとAbstractModule実装をつくって
Guice単独にしないと駄目かもしれない。



うーん、数珠つなぎ状のXMLファイルとか
configure()化するのはちょっときつそうだなあ..


だれかコンバータつくってくれないものかなあ...

とここでつぶやいてみる。


1 件のコメント:

師子乃 さんのコメント...

おはようございます。

こうしたコンバータが欲しいと思う時、多々ありますよね。

既存アプリケーションをK8s上でコンテナ化して動かす場合の設計注意事項メモ

既存アプリをK8sなどのコンテナにして動かすには、どこを注意すればいいか..ちょっと調べたときの注意事項をメモにした。   1. The Twelve Factors (日本語訳からの転記) コードベース   バージョン管理されている1つのコードベースと複数のデプロイ 依存関係 ...