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以前ではもうちょっと面倒なやり方になると思います。

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

0 件のコメント:

コメントを投稿