私は geotools で遊んでいて、データ アクセス クラスの 1 つをプロキシして、それがコードでどのように使用されているかを追跡しようと考えました。
動的プロキシをコーディングし、そこに FeatureSource (インターフェイス) をラップすると、うまくいきました。次に、featureSource が返す主な機能は FeatureCollection を返すことなので (FeatureSource は SQL DataSource に、featureCollection は SQL ステートメントに類似しています)、featureSource によって返される推移的なオブジェクトのいくつかも調べたいと思いました。
私の呼び出しハンドラでは、基礎となるオブジェクトに呼び出しを渡し、ターゲットクラス/メソッド/引数と結果を出力しましたが、FeatureCollection (別のインターフェイス) を返す呼び出しについては、そのオブジェクトをプロキシ (同じクラスだが新しいインスタンス、それは問題ではないはずですか?) そしてそれを返しました。バム!クラスキャストの例外:
java.lang.ClassCastException: $Proxy5 cannot be cast to org.geotools.feature.FeatureCollection
at $Proxy4.getFeatures(Unknown Source)
at MyClass.myTestMethod(MyClass.java:295)
呼び出しコード:
FeatureSource<SimpleFeatureType, SimpleFeature> featureSource = ... // create the FS
featureSource = (FeatureSource<SimpleFeatureType, SimpleFeature>) FeatureSourceProxy.newInstance(featureSource, features);
featureSource.getBounds();// ok
featureSource.getSupportedHints();// ok
DefaultQuery query1 = new DefaultQuery(DefaultQuery.ALL);
FeatureCollection<SimpleFeatureType, SimpleFeature> results = featureSource.getFeatures(query1); //<- explosion here
プロキシ:
public class FeatureSourceProxy implements java.lang.reflect.InvocationHandler {
private Object target;
private List<SimpleFeature> features;
public static Object newInstance(Object obj, List<SimpleFeature> features) {
return java.lang.reflect.Proxy.newProxyInstance(
obj.getClass().getClassLoader(),
obj.getClass().getInterfaces(),
new FeatureSourceProxy(obj, features)
);
}
private FeatureSourceProxy(Object obj, List<SimpleFeature> features) {
this.target = obj;
this.features = features;
}
public Object invoke(Object proxy, Method m, Object[] args)throws Throwable{
Object result = null;
try {
if("getFeatures".equals(m.getName())){
result = interceptGetFeatures(m, args);
}
else{
result = m.invoke(target, args);
}
}
catch (Exception e) {
throw new RuntimeException("unexpected invocation exception: " + e.getMessage(), e);
}
return result;
}
private Object interceptGetFeatures(Method m, Object[] args) throws Exception{
return newInstance(m.invoke(target, args), features);
}
}
プロキシされたインターフェイスからインターフェイスのプロキシを動的に返すことは可能ですか、それとも何か間違っていますか? 乾杯!