fundo
Nos cenários de chamada de interface RPC ou usando cenários dinâmicos de proxy, ocorre ocasionalmente uma exceção de exceção, ou em um cenário de reflexão, ocorre uma invocaçãoTargetexception, que é inconsistente com a exceção que esperamos, e as informações de exceção real estão ocultas em uma pilha profunda. Este artigo se concentrará na análise da UND -GLAREWLOWABLEEXCECTION
Dê uma conclusão primeiro
Ao usar a interface proxy dinâmica do JDK, se uma exceção detectada for lançada durante a execução do método, mas a assinatura do método não declarar a exceção, ela será envolvida na classe Proxy como uma exceção não declarada.
Restaurar o problema
// interface Definição da interface pública ISERVICE {void Foo () lança sqLexception;} public class ServiceImpl implementa o iservice {@Override public void Foo () lança sqLexception {lança nova sqLException ("Testo o teste de uma exceção verificada"); }} // Classe public dinâmica de procuração iserviceProxy implementa InvocationHandler {destino de objeto privado; IserviceProxy (Object Target) {this.target = Target; } @Override Public Object Invoke (proxy do objeto, método do método, objeto [] args) lança arremesso {return métod.invoke (alvo, args); }} public class Melhorest {public static void main (string [] args) {iService Service = new ServiceImpl (); Iservice serviceproxy = (iservice) proxy.newproxyInstance (Service.getClass (). GetClassLoader (), Service.getClass (). GetInterfaces (), new iserviceProxy (serviço)); tente {serviceProxy.foo (); } catch (Exceção e) {e.printStackTrace (); }}}Execute o manutenção acima e a pilha de exceção é
java.lang.reflelect.undeCLaredHrowableException em com.sun.proxy. $ proxy0.foo (fonte desconhecida) em com.learn.reflect.maintest.main (manutest.java:16) causada por: java.lang.reflect.invocationTarGeTexception at Sung.LaRActreflectionException) Método) em sun.reflelect.nativemethodaccessorimpl.invoke (nativemethodAccessorimpl.java:62) em sun.reflelect.delegatingMethodAccessorimpl.invake (delegatingMethodaccess.Java:43) em java.lang.lang.relect.Relect.Relect.Relect.Relect (DeLegatingMethodaccess.Java:43) em java.lang.lang.relect.Relect.Relect.Relect.Relect.Relect.Relect (DeLegatingMethodaccess.Java:43) em java.lang.lang.relect.Relect. com.learn.reflect.IServiceProxy.invoke (iserviceProxy.java:19) ... 2 Moreused por: java.sql.SqLEXCIMECTION: Teste uma exceção verificada em com.learn.reflect.serviceImpl.foo (ServiceImpl.Java:11) ... 7 mais
O que esperamos é
Java.SQL.SQLEXCECCO: Teste uma exceção verificada em com.learn.reflect.serviceImpl.foo (ServiceImpl.java:11) ...
Análise de causa
Na restauração do problema acima, a verdadeira SqLexception é embrulhada em duas camadas, primeiro embrulhada pela InvocationTargeTexception, e depois embrulhada pela Unde -GlaryWrableAxception. Entre eles, a InvocationTargeTexception é a exceção detectada, e a UND -GLAROWHERTHOWABLEEXCECTION é a exceção de tempo de execução. Por que está embrulhado? Também começa com a classe proxy gerada por proxy dinâmico.
O proxy dinâmico do JDK gerará a classe de implementação específica da interface delegada no tempo de execução. Geramos manualmente o arquivo de classe através do ProxyGenerator e, em seguida, usamos a ideia para analisar o arquivo de classe para obter a classe de proxy específica: intercepte a peça:
Classe final pública iserviceProxy $ 1 estende a proxy implementa o ISERVICE {Método estático privado m1; Método estático privado m2; Método estático privado m3; Método estático privado m0; public iserviceProxy $ 1 (InvocationHandler var1) lança {super (var1); } public final void foo () lança sqLexception {try {super.h.invoke (this, m3, (objeto []) null); } Catch (RUNTimeException | SQLEXCECCIONE | ERRO VAR2) {tiro var2; } catch (throwable var3) {lança a nova não -declaração de abordagem (var3); }} static {try {m1 = class.ForName ("java.lang.object"). m2 = classe.ForName ("java.lang.object"). getMethod ("tostring", nova classe [0]); m3 = classe.ForName ("com.learn.reflect.IService"). getMethod ("foo", nova classe [0]); m0 = classe.ForName ("java.lang.object"). getMethod ("hashcode", nova classe [0]); } catch (nosuchmethodException var2) {tiro novo noschmethoderror (var2.getMessage ()); } Catch (ClassNotFoundException var3) {THROW NOVA NOCLASSDEFFOUNDERROR (VAR3.GETMESSAGE ()); }}}Ao chamar o método Foo da "classe delegada", o método foo da classe proxy iserviceProxy $ 1 é realmente chamado, e a lógica principal da classe proxy é chamar o método de invocar o InvocationHandler. A lógica do manuseio de exceção é lançar diretamente a RunTimeException, a exceção declarada pela interface, e o erro é lançado e outras exceções são embrulhadas como Und -GarasarwlowableException. Neste ponto, talvez você já tenha conseguido, talvez tenha uma pergunta, na implementação da interface, é de fato lançar uma nova SQLEXCECTION, por que ainda está embrulhada? Vejamos o método de invasão do ISERVICEPROXY. Ele executa diretamente o método de destino através da reflexão. Este é o problema. Method.inVoke (objeto obj, objeto ... args) A declaração do método foi explicada que, se o método de destino lançar uma exceção, será envolvido como uma invocaçãoTargeTexception. (Para detalhes, verifique Javadoc)
Portanto, o resumo é: Na implementação específica do método, a SQLEXCECTION é lançada e é refletida e embrulhada como uma invocaçãoTargeTexception. Esta é uma exceção verificada. Quando a classe de proxy lida com a exceção, descobre que a exceção não é declarada na interface, por isso é embalada como uma exceção não declarada.
Solução
No órgão do método Invoke que implementa a InvocationHandler, tente pegar o método.invoke (Target, args); Ligue e jogue a causa da InvocationTargeTexception. Agora mesmo:
@Override Public Object Invoke (proxy do objeto, método do método, objeto [] args) lança jogável {try {return métod.invoke (alvo, args); } catch (InvocationTargeTexception e) {throw E.getcause (); }}Fora do tópico
Por que uma exceção verificada não declarada na classe Proxy se transforma em uma UND -GLARELHELWABLEABLEEXCECTION? Devido ao princípio da herança Java: quando uma subclasse substitui a classe pai ou um método que implementa a interface pai, a exceção arremessada deve estar dentro da lista de exceções suportada pelo método original. A classe proxy implementa a interface dos pais ou substitui o método da classe pai
consulte
https://www.ibm.com/developerworks/cn/java/j-lo-proxy1/index.html#icomments
Resumir
O acima é o conteúdo inteiro deste artigo. Espero que o conteúdo deste artigo tenha certo valor de referência para o estudo ou trabalho de todos. Se você tiver alguma dúvida, pode deixar uma mensagem para se comunicar. Obrigado pelo seu apoio ao wulin.com.