Hintergrund
In RPC -Schnittstellen -Aufrufszenarien oder Verwendung dynamischer Proxy -Szenarien tritt gelegentlich eine nicht deklarierte Dhrowable -Option auf, oder in einem Reflexionsszenario tritt ein InvocationTargetException auf, das mit der von uns erwarteten Ausnahme inkonsistent ist, und die realen Ausnahmeinformationen sind in einem tieferen Stapel versteckt. Dieser Artikel konzentriert sich auf die Analyse von nicht deklarierter Drüsebuchabnahme
Zuerst eine Schlussfolgerung geben
Bei Verwendung der JDK -Dynamik -Proxy -Schnittstelle, wenn eine erkannte Ausnahme während der Ausführung der Methode ausgelöst wird, die Methode -Signatur jedoch nicht die Ausnahme deklariert, wird sie in die Proxy -Klasse als nicht deklarierter Drowablexception eingewickelt.
Das Problem wiederherstellen
// Schnittstellendefinition öffentliche Schnittstelle Iservice {void foo () löst SQLEXception aus;} öffentliche Klasse ServiceImpl implementiert iService {@Override public void foo () löst SQLEXception aus {neue SQLEXception ("i testet eine geprüfte Ausnahme); }} // Dynamic Proxy Public Class IServiceProxy implementiert InvocationHandler {private Objektziel; IServiceProxy (Objektziel) {this.target = Ziel; } @Override public Object Invoke (Object Proxy, Methode Methode, Object [] args) wirft Throwable {return methode.invoke (Ziel, args) aus; }} public class halten {public static void main (String [] args) {iService service = new ServiceImpl (); IService serviceProxy = (iService) proxy.newProxyInstance (service.getClass (). GetClassloader (), service.getClass (). GetInterfaces (), New IServiceProxy (Service)); try {serviceProxy.foo (); } catch (Ausnahme e) {e.printstacktrace (); }}}Führen Sie die oben genannten Wältes durch und der Ausnahmestapel ist
java.lang.reflect.undeclaredThrowablexception bei com.sun.proxy. Methode) bei sun.reflect.nativemethodaccessorimpl.invoke (nativemethodaccessorimpl.java:62) bei sun.reflect.delegatingMethodaccessorimpl.invoke (DelegatingMethodaccessorimpl.java:43) at java.lang.lang.Ava.lang.Lang. com.learn.reflect.iserviceproxy.invoke (iserviceproxy.java:19) ... 2 meorecausgedes von: java.sql.sqlexception: Ich testet eine geprüfte Ausnahme auf Com.learn.reflect.ServiceImpl.foo (ServiceImpl.java:11) ... 7 mehr
Was wir erwarten, ist
java.sql.sqlexception: Ich teste eine geprüfte Ausnahme bei com.learn.reflect.serviceImpl.foo (serviceImpl.java:11) ...
Analyse verursachen
In der obigen Problemrestauration ist die eigentliche SQLEXception in zwei Ebenen eingewickelt, zuerst durch InvocationTargetException und dann von nicht deklarierter Drüseberichtungsbarkeit eingewickelt. InvocationTargetException ist unter ihnen die erkannte Ausnahme, und nicht deklarierter DrowsException ist die Laufzeitausnahme. Warum ist es verpackt? Es beginnt auch mit der Proxy -Klasse, die von Dynamic Proxy generiert wird.
Der JDK Dynamic Proxy generiert zur Laufzeit die spezifische Implementierungsklasse der Delegiertenschnittstelle. Wir generieren die Klassendatei manuell über Proxygenerator und verwenden dann IDEE, um die Klassendatei zu analysieren, um die spezifische Proxy -Klasse zu erhalten: Abfangen das Teil:
öffentliche endgültige Klasse iServiceProxy $ 1 erweitert Proxy implementiert iService {private statische Methode M1; private statische Methode M2; private statische Methode M3; private statische Methode M0; public iServiceProxy $ 1 (invocationHandler var1) löst {Super (var1) aus; } public Final void foo () löst SQLEXception aus {try {super.h.invoke (this, m3, (Object []) null); } catch (RunTimeException | SQLEXception | Fehler var2) {throw var2; } catch (throwable var3) {werfen Sie neue nicht deklarierte ThrowableException (var3); }} static {try {m1 = class.forname ("java.lang.object"). getMethod ("Equals", New Class [] {class.forname ("java.lang.Object")}); m2 = class.Forname ("java.lang.object"). getMethod ("tostring", neue Klasse [0]); M3 = class.Forname ("com.learn.reflect.iservice"). GetMethod ("foo", neue Klasse [0]); M0 = class.Forname ("java.lang.object"). getMethod ("HashCode", neue Klasse [0]); } catch (NoSuchMethodException var2) {neue NoSuchMethoderror werfen (var2.getMessage ()); } catch (classNotFoundException var3) {neue noclassDeffoundError werfen (var3.getMessage ()); }}}Wenn Sie die FOO -Methode der "Delegate -Klasse" aufrufen, wird die FOO -Methode der Proxy -Klasse IserviceProxy $ 1 tatsächlich aufgerufen, und die Hauptlogik der Proxy -Klasse besteht darin, die Invoke -Methode des InvocationHandlers aufzurufen. Die Logik der Ausnahmebehandlung besteht darin, RunTimeException direkt zu werfen, die von der Schnittstelle deklarierte Ausnahme, und der Fehler wird geworfen, und andere Ausnahmen werden als nicht deklarierter Throwablexception eingewickelt. An diesem Punkt haben Sie es vielleicht bereits bekommen, vielleicht haben Sie eine Frage, in der Schnittstellenimplementierung, es ist in der Tat neue SQLEXception, warum ist es noch verpackt? Schauen wir uns die Invoke -Methode von IserviceProxy an. Es führt die Zielmethode direkt durch Reflexion aus. Das ist das Problem. Method.invoke (Object OBJ, Objekt ... args) Die Methode wurde erklärt, dass die Zielmethode, wenn sie eine Ausnahme ausgelöst hat, als InvocationTargetException eingewickelt wird. (Weitere Informationen finden Sie in Javadoc)
Daher ist die Zusammenfassung: In der spezifischen Methode -Implementierung wird die SQLEXception geworfen und als InvocationTargetException reflektiert und verpackt. Dies ist eine geprüfte Ausnahme. Wenn die Proxy -Klasse mit der Ausnahme umgeht, wird festgestellt, dass die Ausnahme in der Schnittstelle nicht deklariert ist, sodass sie als nicht deklarierter Drow -Anfang verpackt wird.
Lösung
Versuchen Sie, die Methode zu fangen. Rufen Sie an und werfen Sie die Ursache der InvocationTargetException. Im Augenblick:
@Override Public Object Invoke (Object Proxy, Methode Methode, Object [] args) löscht Throwable {try {return methode.invoke (Ziel, args); } catch (invocationTargetException e) {throw e.getCause (); }}Off -Thema
Warum wird eine nicht deklarierte Ausnahme in der Proxy -Klasse in eine nicht deklarierte Drüsungsabteilung? Aufgrund des Java -Vererbungsprinzips: Wenn eine Unterklasse die übergeordnete Klasse oder eine Methode überschreibt, die die übergeordnete Schnittstelle implementiert, muss die geworfene Ausnahme innerhalb der Ausnahmliste liegen, die von der ursprünglichen Methode unterstützt wird. Die Proxy -Klasse implementiert die übergeordnete Schnittstelle oder überschreibt die übergeordnete Klassenmethode
beziehen sich auf
https://www.ibm.com/developerworks/cn/java/j-lo--proxy1/index.html#icommments
Zusammenfassen
Das obige ist der gesamte Inhalt dieses Artikels. Ich hoffe, dass der Inhalt dieses Artikels einen gewissen Referenzwert für das Studium oder die Arbeit eines jeden hat. Wenn Sie Fragen haben, können Sie eine Nachricht zur Kommunikation überlassen. Vielen Dank für Ihre Unterstützung bei Wulin.com.