2011年4月24日日曜日

パッケージ内のクラス一覧を取得する

普段からSpringなどのDIフレームワークを使っているのですが、 Springでは、xmlファイルでパッケージ名を指定すると、そのパッケージ内のクラスをインスタンス化して注入してくれます。
便利な機能なのでよく使うのですが、どのようにしてパッケージ名からクラス一覧を取得しているかを知りませんでした。

実装を知るには、ソースを読めば手っ取り早いですが、今回はソースは読まずに、実装方法はこんな感じだろうかと考えてみます。

パッケージ名から、そのパッケージ内のクラス一覧を取得する
  1. import javax.tools.DiagnosticCollector;  
  2. import javax.tools.JavaCompiler;  
  3. import javax.tools.JavaFileManager;  
  4. import javax.tools.JavaFileObject;  
  5. import javax.tools.StandardLocation;  
  6. import javax.tools.ToolProvider;  
  7.   
  8. /** 
  9.  * 指定パッケージ内のクラス情報のコレクションを返す。 
  10.  *  
  11.  * @param x_packageName パッケージ名 
  12.  * @return クラス情報のコレクション 
  13.  */  
  14. public static Collection<Class<? extends Object>> getClasses(String x_packageName) {  
  15.  JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();  
  16.  JavaFileManager fm = compiler.getStandardFileManager(new DiagnosticCollector<JavaFileObject>(), nullnull);  
  17.   
  18.  // 一覧に含めるオブジェクト種別。(クラスのみを含める)  
  19.  Set<JavaFileObject.Kind> kind = new HashSet<JavaFileObject.Kind>();  
  20.  kind.add(JavaFileObject.Kind.CLASS);  
  21.   
  22.  Collection<Class<? extends Object>> results = new ArrayList<Class<? extends Object>>();  
  23.   
  24.  Iterable<JavaFileObject> jfos = null;  
  25.  try {  
  26.   jfos = fm.list(StandardLocation.CLASS_PATH, x_packageName, kind, false);  
  27.  } catch (IOException e) {  
  28.   e.printStackTrace();  
  29.  }  
  30.  if (jfos != null) {  
  31.   for (JavaFileObject fos : jfos) {  
  32.    try {  
  33.     Class<? extends Object> clazz = Class.forName(x_packageName + "." + fos.getName().replaceAll("\\.class$"""));  
  34.     if (clazz.isEnum() || clazz.isInterface() || clazz.isAnonymousClass() || clazz.isLocalClass()) {  
  35.      continue;  
  36.     }  
  37.     results.add(clazz);  
  38.    } catch (ClassNotFoundException e) {  
  39.     e.printStackTrace();  
  40.    }  
  41.   }  
  42.  }  
  43.  return results;  
  44. }  
使用するのはjava.lang.reflectパッケージのクラスかと思っていましたが、実際はjavax.toolsパッケージのクラスです。
これらのクラスがあるのは、javaのバージョン1.6以降のようです。
バージョン1.5以前ではもうちょっと面倒なやり方になると思います。

フレームワークの実装を知ることで、フレームワークの使い方を知ります。
今回は、実装を想像しただけですが...

2011年4月18日月曜日

ウェイトアップしています

現在、私は週2回ほど筋トレをしています。 始めたのは2010年8月頃で、半年以上は継続していることになります。
体の変化については、体重62kgから68kgになり、体脂肪は14%から15.5%になりました。 今のところはいい感じにウェイトアップしています。 ちなにみ、身長は180cmなので、まだまだ痩せ体型といえます。

今回は、筋トレについて。 まだまだ素人ですが、これまでの私の経験に基づいて、ウェイトアップの方法を説明します。
この説明が参考になる人は、おそらく私のような太りにくい痩せ型の体型でしょう。 該当する人も、そうでない人も、一例として見てもらいたいと思います。

まず、ウェイトアップで最も重要なのは、トレーニングよりも栄養の摂取です。 なので、今回は私が日頃、どのような栄養(サプリメント)を摂取しているかと、それはどのタイミングなのかについて説明します。

プロテイン
種類原材料特徴
ホエイ牛乳吸収が速い
カゼイン牛乳吸収が遅い
エッグ良質のタンパク質短時間で消化
大豆大豆健康に良く消化が早い
ザ・バルクアップトレーニングより
とりあえず、ホエイと大豆(ソイ)だけ注目しておけばよいです。 摂取する種類と時間については、運動前後はホエイ、就寝前は大豆(ソイ)が妥当でしょう。
炭水化物
特に痩せ体質の人が筋肉量アップをするには炭水化物がタンパク質以上に重要な役割を果たすと考えています。
ザ・バルクアップトレーニングより
サイトの説明通りで、プロテインより重要です。 炭水化物の摂取量が少ないと、体重は増えません。 私は以前に炭水化物を制限してトレーニングしていた事があるのですが、そのときは体重は全く増えず、体脂肪だけが落ちていきました。 それはそれでありかと思われるかもしれませんが、トレーニングしている事と健康面から考えて、十分に摂取すべきです。 少し多めに摂取して、超過した分はランニングすることで落とすくらいがちょうどいいでしょう。
BCAA
トレーニング時の疲労の軽減にも効果がありますのでハードなトレーニングでも疲労が軽減することで運動パフォーマンスを最大限に生かす事ができ、よりトレーニング効果を高めてくれます。
ザ・バルクアップトレーニングより
サイトの説明通りで、効率よくトレーニングするために必要になります。 筋トレの目的は、筋肉に可能な限り負荷をかけることです。 トレーニングをしていて、体力が無くなるより先に筋肉に十分な負荷をかけられればいいのですが、 プロテイン等を摂取していると、それよりも先に体力が無くなる事がありえます。 そうなると、効率よく負荷をかけ続けることが難しくなるので、疲労を軽減するBCAAをトレーニング前に摂取しておきます。
グルタミン
グルタミンは筋肉の分解を抑えてくれるのでウエイトとレーニン後には必ず摂っておきたいサプリメントです。
グルタミンは体内のアミノ酸の60%を占めていることからも異化を抑えてくれるサプリメントの中でも一番効果的です。
ザ・バルクアップトレーニングより
筋肉を増加させるための筋トレですが、その筋トレ中(主に筋トレ後)にも筋肉は異化(分解みたいなもの)します。 そもそも、筋肉が異化するのは体内のタンパク質(アミノ酸)が不足しているためなので、異化する筋肉の代替として摂取します。 即効性のプロテインのようなものと考えればいいかと思います。
私が購入しているサプリメント
グルタミン DNS グルタミンパウダー(300g)
BCAA DNS BCAAパウダー(200g)
ホエイプロテイン ザバス(SAVAS) ホエイプロテイン100 ココア味 360g
ホエイプロテイン(ウェイトアップ) ザバス(SAVAS) ウェイトアップ 360g
大豆(ソイ)プロテイン ザバス(SAVAS) ウエイトダウン 360g
ホエイプロテイン(ウェイトアップ)はタンパク質の量が少なく、炭水化物が含まれています。
全部一括で買い揃えると相当の金額になります。
いったん揃えてしまえば、あとは無くなったものを補充していくだけなので、金額的にはそれほど気にならないと思います。
上記のプロテインは飲みやすさで選んでいますが、探せば他にも安いものや、高価なものがあります。
実際にはどのように摂取しているか
週7日のうち、2日がトレーニング日で、時間帯は18:00~21:00の間の90分です。その前後と就寝前に摂取しています。
また、運動後はすぐに炭水化物を摂取するようにします。無理矢理でも詰め込みます。
トレーニング前トレーニング後就寝前
トレーニング日ホエイプロテイン
BCAA
ホエイプロテイン(ウェイトアップ)
グルタミン
トレーニングの無い日大豆プロテイン
グルタミン
注意してほしい点が一つ
サプリメントを摂取するということについて、特にホエイプロテインは動物性タンパク質なので、 どうしても胃や腸に大きな負担をかけてしまいます。
サプリメントの過剰な摂取は避けて、日頃の食事で野菜やヨーグルト、ビタミン剤を摂るようにしたほうがよいでしょう。
ちなみに、私は、スキムミルクで作る自家製ヨーグルトを毎朝食べて腸の調子を整えています。

2011年4月8日金曜日

Struts2 + Spring + Slim3 サンプル

今回は、 【修正版】 Struts2 + Spring + Slim3で構築したフレームワークを使ってサンプルのソースを書いてみます。

サンプルは簡単なデータ登録と表示の実装です。

作成するファイル一覧
今回、作成するファイルは以下の通りです。それ以外のファイルは一切触りません。
ファイル一覧
/src/com/brightgenerous/s3/sample/action/Sample_Action.java
/src/com/brightgenerous/s3/sample/action/Sample_Service.java
/src/com/brightgenerous/s3/sample/action/Sample_ServiceImpl.java
/src/com/brightgenerous/s3/sample/data/model/Account.java
/src/com/brightgenerous/s3/sample/data/meta/AccountMeta.java
/war/WEB-INF/content/sample/index.jsp
/war/WEB-INF/content/sample/show.jsp
「Account.java」と「AccountMeta.java」はSlim3のプラグインを使って自動生成します。
javaのソースコード
1.com.brightgenerous.s3.sample.action.Sample_Action.java
  1. package com.brightgenerous.s3.sample.action;  
  2.   
  3. import java.util.List;  
  4.   
  5. import org.apache.struts2.convention.annotation.Action;  
  6. import org.apache.struts2.convention.annotation.Namespace;  
  7. import org.apache.struts2.convention.annotation.ParentPackage;  
  8. import org.springframework.beans.factory.annotation.Autowired;  
  9.   
  10. import com.brightgenerous.s3.sample.data.model.Account;  
  11. import com.opensymphony.xwork2.ModelDriven;  
  12.   
  13. @ParentPackage("struts-default")  
  14. @Namespace("/sample")  
  15. public class Sample_Action implements ModelDriven<account> {  
  16.   
  17.  private Account p_model = new Account();  
  18.   
  19.  @Autowired  
  20.  private Sample_Service p_service;  
  21.   
  22.  @Override  
  23.  public Account getModel() {  
  24.   return p_model;  
  25.  }  
  26.   
  27.  public List<account> getAccounts() {  
  28.   return p_service.get();  
  29.  }  
  30.   
  31.  /** 
  32.   * [Action:初期表示] 
  33.   */  
  34.  @Action("index")  
  35.  public String index() {  
  36.   
  37.   return "index";  
  38.  }  
  39.   
  40.  /** 
  41.   * [Action:表示] 
  42.   */  
  43.  @Action("show")  
  44.  public String show() {  
  45.   
  46.   return "show";  
  47.  }  
  48.   
  49.  /** 
  50.   * [Action:登録] 
  51.   */  
  52.  @Action("regist")  
  53.  public String regist() {  
  54.   p_service.regist(p_model);  
  55.   return show();  
  56.  }  
  57. }  
  58. </account></account>  
2.com.brightgenerous.s3.sample.action.Sample_Service.java
  1. package com.brightgenerous.s3.sample.action;  
  2.   
  3. import java.util.List;  
  4.   
  5. import com.brightgenerous.s3.sample.data.model.Account;  
  6.   
  7. interface Sample_Service {  
  8.   
  9.  Account regist(Account x_account);  
  10.   
  11.  List<Account> get();  
  12. }  
3.com.brightgenerous.s3.sample.action.Sample_ServiceImpl.java
  1. package com.brightgenerous.s3.sample.action;  
  2.   
  3. import java.util.List;  
  4.   
  5. import org.slim3.datastore.Datastore;  
  6. import org.springframework.stereotype.Component;  
  7.   
  8. import com.brightgenerous.s3.sample.data.meta.AccountMeta;  
  9. import com.brightgenerous.s3.sample.data.model.Account;  
  10.   
  11. @Component  
  12. class Sample_ServiceImpl implements Sample_Service {  
  13.   
  14.  @Slim3GlobalTransaction  
  15.  private GlobalTransaction p_tx;  
  16.   
  17.  @Override  
  18.  public Account regist(Account x_account) {  
  19.   p_tx.put(x_account);  
  20.   return x_account;  
  21.  }  
  22.   
  23.  @Override  
  24.  public List<account> get() {  
  25.   AccountMeta meta = AccountMeta.get();  
  26.   return Datastore.query(meta).asList();  
  27.  }  
  28. }  
  29. </account>  
4.com.brightgenerous.s3.sample.data.model.Account.java
  1. package com.brightgenerous.s3.sample.data.model;  
  2.   
  3. import java.io.Serializable;  
  4.   
  5. import com.google.appengine.api.datastore.Key;  
  6.   
  7. import org.slim3.datastore.Attribute;  
  8. import org.slim3.datastore.Model;  
  9.   
  10. @Model(schemaVersion = 1)  
  11. public class Account implements Serializable {  
  12.   
  13.  private static final long serialVersionUID = 1L;  
  14.   
  15.  @Attribute(primaryKey = true)  
  16.  private Key key;  
  17.   
  18.  @Attribute(version = true)  
  19.  private Long version;  
  20.   
  21.  private String nickname;  
  22.   
  23.  private String email;  
  24.   
  25.  /** 
  26.   * Returns the key. 
  27.   *  
  28.   * @return the key 
  29.   */  
  30.  public Key getKey() {  
  31.   return key;  
  32.  }  
  33.   
  34.  /** 
  35.   * Sets the key. 
  36.   *  
  37.   * @param key the key 
  38.   */  
  39.  public void setKey(Key key) {  
  40.   this.key = key;  
  41.  }  
  42.   
  43.  /** 
  44.   * Returns the version. 
  45.   *  
  46.   * @return the version 
  47.   */  
  48.  public Long getVersion() {  
  49.   return version;  
  50.  }  
  51.   
  52.  /** 
  53.   * Sets the version. 
  54.   *  
  55.   * @param version the version 
  56.   */  
  57.  public void setVersion(Long version) {  
  58.   this.version = version;  
  59.  }  
  60.   
  61.  public String getNickname() {  
  62.   return nickname;  
  63.  }  
  64.   
  65.  public void setNickname(String x_nickname) {  
  66.   nickname = x_nickname;  
  67.  }  
  68.   
  69.  public String getEmail() {  
  70.   return email;  
  71.  }  
  72.   
  73.  public void setEmail(String x_email) {  
  74.   email = x_email;  
  75.  }  
  76.   
  77.  @Override  
  78.  public int hashCode() {  
  79.   final int prime = 31;  
  80.   int result = 1;  
  81.   result = prime * result + ((key == null) ? 0 : key.hashCode());  
  82.   return result;  
  83.  }  
  84.   
  85.  @Override  
  86.  public boolean equals(Object obj) {  
  87.   if (this == obj) {  
  88.    return true;  
  89.   }  
  90.   if (obj == null) {  
  91.    return false;  
  92.   }  
  93.   if (getClass() != obj.getClass()) {  
  94.    return false;  
  95.   }  
  96.   Account other = (Account) obj;  
  97.   if (key == null) {  
  98.    if (other.key != null) {  
  99.     return false;  
  100.    }  
  101.   } else if (!key.equals(other.key)) {  
  102.    return false;  
  103.   }  
  104.   return true;  
  105.  }  
  106. }  
Slim3プラグインのantから「gen-model」を選択して、自動生成されたソースをもとにしています。
追加部分は「nickname」と「email」の変数と、そのgetter・setterだけです。
jspのソースコード
1./WEB-INF/content/sample/index.jsp
  1. <%@page pageEncoding="UTF-8" isELIgnored="false" session="false"%>  
  2. <%@ taglib uri="/struts-tags" prefix="s" %>  
  3.   
  4. <s:form>  
  5.  <s:textfield label="ニックネーム" name="nickname"></s:textfield>  
  6.  <s:textfield label="Email" name="email"></s:textfield>  
  7.  <s:submit action="regist"></s:submit>  
  8. </s:form>  
  9.    
  10.   
  11.  <s:a action="show">表示</s:a>  
2./WEB-INF/content/sample/show.jsp
  1. <%@page pageEncoding="UTF-8" isELIgnored="false" session="false"%>  
  2. <%@ taglib uri="/struts-tags" prefix="s" %>  
  3.   
  4. <s:iterator value="%{getAccounts()}">  
  5.   </s:iterator><table border="1">  
  6.  <tbody>  
  7. <tr><th>ニックネーム</th><th>Email</th></tr>  
  8.   
  9. <tr>  
  10.    <td><s:property value="%{getNickname()}"></s:property></td>  
  11.    <td><s:property value="%{getEmail()}"></s:property></td>  
  12.   </tr>  
  13. </tbody></table>  
  14. <s:a action="index">戻る</s:a>  

以上で実装は完了です。

ここまで書いておいて、言ってしまうのですが、GlobalTransactionのインスタンスが直に注入されるのは気持ち悪いです。無理にSpringを使うことは無いと思い直しました。さらに、Springだけが原因かは調べていませんが、spin-upの時間もかなり掛かっています。

実行してみる
折角なので、動かしてみます。

Transactionは上手く機能しました。画像ではお見せできていませんが、例外が発生した場合は、ちゃんとrollbackしてくれています。

なんとかNo-configurationで書けたのですが、この方法を続けるにはDIを軽量化する必要があるのかなぁ...と思ってみたりみなかったり。

近いうちに、GWTとStruts2の連携についても書ければいいかな、なんて考えています。