Quindi sto giocando con i geotools e ho pensato di eseguire il proxy di una delle loro classi di accesso ai dati e di tracciare il modo in cui sono stati utilizzati nella loro codice.Java.lang.reflect.Proxy che restituisce un altro proxy dai risultati di chiamata in ClassCastException sull'assegnazione
Ho codificato un proxy dinamico e racchiuso una FeatureSource (interfaccia) al suo interno e ne è uscito felicemente. Quindi ho voluto esaminare alcuni degli oggetti transitivi restituiti da featureSource, poiché la caratteristica principale di FeatureSource è restituire un FeatureCollection (FeatureSource è analogo a un sql DataSource e featurecollection a un'istruzione sql).
nel mio invocationhandler ho appena passato la chiamata attraverso l'oggetto sottostante, stampando la classe/metodo/args di destinazione e il risultato come sono andato, ma per le chiamate che hanno restituito un FeatureCollection (un'altra interfaccia), ho spostato quell'oggetto in il mio proxy (la stessa classe ma una nuova istanza, non dovrebbe importare, dovrebbe?) e lo ha restituito. BAM! eccezione Classcast:
java.lang.ClassCastException: $Proxy5 cannot be cast to org.geotools.feature.FeatureCollection
at $Proxy4.getFeatures(Unknown Source)
at MyClass.myTestMethod(MyClass.java:295)
il codice chiamante:
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
Proxy:
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);
}
}
E 'possibile restituire dinamicamente proxy di interfacce da un proxy interfaccia o sto facendo qualcosa di sbagliato? evviva!
funziona perfettamente !!wow grazie per quello, a ben vedere è ovvio che avrei dovuto immaginarlo, per qualche ragione pensavo che getInterfaces() avrebbe restituito * tutte * le interfacce implementate, non solo quelle implementate direttamente dalla classe. – matao