`
wxyfighting
  • 浏览: 191879 次
  • 性别: Icon_minigender_1
  • 来自: 上海
文章分类
社区版块
存档分类
最新评论

Hessian源码分析(二)------ HessianProxy

 
阅读更多

Hessian在客户端一块采用Proxy模式,当客户端调用远程接口时,HessianProxy会代理这个动作,在invoke方法中,把客户端请求的方法和参数序列化为预订格式的输出流,主要流程如下图所示:

下面我将详细解析一下invoke源码:

  1. publicObjectinvoke(Objectproxy,Methodmethod,Object[]args)
  2. throwsThrowable
  3. {
  4. StringmangleName;
  5. synchronized(_mangleMap){
  6. mangleName=_mangleMap.get(method);
  7. }
  8. if(mangleName==null){
  9. StringmethodName=method.getName();
  10. Class[]params=method.getParameterTypes();
  11. //equalsandhashCodearespecialcased
  12. if(methodName.equals("equals")
  13. &&params.length==1&&params[0].equals(Object.class)){
  14. Objectvalue=args[0];
  15. if(value==null||!Proxy.isProxyClass(value.getClass()))
  16. returnnewBoolean(false);
  17. HessianProxyhandler=(HessianProxy)Proxy.getInvocationHandler(value);
  18. returnnewBoolean(_url.equals(handler.getURL()));
  19. }
  20. elseif(methodName.equals("hashCode")&&params.length==0)
  21. returnnewInteger(_url.hashCode());
  22. elseif(methodName.equals("getHessianType"))
  23. returnproxy.getClass().getInterfaces()[0].getName();
  24. elseif(methodName.equals("getHessianURL"))
  25. return_url.toString();
  26. elseif(methodName.equals("toString")&&params.length==0)
  27. return"HessianProxy["+_url+"]";
  28. if(!_factory.isOverloadEnabled())
  29. mangleName=method.getName();
  30. else
  31. mangleName=mangleName(method);
  32. synchronized(_mangleMap){
  33. _mangleMap.put(method,mangleName);
  34. }
  35. }
  36. ......
  37. }

这是invoke的开头,主要干的事情是把methodName缓存起来和过滤一些特殊调用,java反射是个比较耗性能的操作,把methodName缓存起来可以避免每次调用都要从method里得到methodName。另外,对equals、hashCode、getHessianType、getHessianURL等特殊方法的远程调用,HessianProxy不会走远程调用,而是直接返回。

接着往下看:

  1. publicObjectinvoke(Objectproxy,Methodmethod,Object[]args)
  2. throwsThrowable
  3. {
  4. ......
  5. InputStreamis=null;
  6. URLConnectionconn=null;
  7. HttpURLConnectionhttpConn=null;
  8. try{
  9. conn=sendRequest(mangleName,args);
  10. ......
  11. }catch(HessianProtocolExceptione){
  12. thrownewHessianRuntimeException(e);
  13. }finally{
  14. ......
  15. }
  16. }

这段主要是把方法名和参数序列化为网络输出流,并做网络请求,具体逻辑包装在sendRequest方法中:

  1. protectedURLConnectionsendRequest(StringmethodName,Object[]args)
  2. throwsIOException
  3. {
  4. URLConnectionconn=null;
  5. conn=_factory.openConnection(_url);
  6. booleanisValid=false;
  7. try{
  8. //Usedchunkedmodewhenavailable,i.e.JDK1.5.
  9. if(_factory.isChunkedPost()&&conninstanceofHttpURLConnection){
  10. try{
  11. HttpURLConnectionhttpConn=(HttpURLConnection)conn;
  12. httpConn.setChunkedStreamingMode(8*1024);
  13. }catch(Throwablee){
  14. }
  15. }
  16. addRequestHeaders(conn);
  17. OutputStreamos=null;
  18. try{
  19. os=conn.getOutputStream();
  20. }catch(Exceptione){
  21. thrownewHessianRuntimeException(e);
  22. }
  23. if(log.isLoggable(Level.FINEST)){
  24. PrintWriterdbg=newPrintWriter(newLogWriter(log));
  25. os=newHessianDebugOutputStream(os,dbg);
  26. }
  27. AbstractHessianOutputout=_factory.getHessianOutput(os);
  28. out.call(methodName,args);
  29. out.flush();
  30. isValid=true;
  31. returnconn;
  32. }finally{
  33. if(!isValid&&conninstanceofHttpURLConnection)
  34. ((HttpURLConnection)conn).disconnect();
  35. }
  36. }

sendRequest的主要流程是先初始化网络连接,然后用AbstractHessianOutput包装网络输出流,调用AbstractHessianOutput.call(methodName, args)完成网络输出,这个方法的细节会在hessian io的源码解析中详细分析。

下面接着看invoke方法:

  1. publicObjectinvoke(Objectproxy,Methodmethod,Object[]args)
  2. throwsThrowable
  3. {
  4. ......
  5. is=conn.getInputStream();
  6. AbstractHessianInputin=_factory.getHessianInput(is);
  7. in.startReply();
  8. Objectvalue=in.readObject(method.getReturnType());
  9. if(valueinstanceofInputStream){
  10. value=newResultInputStream(httpConn,is,in,(InputStream)value);
  11. is=null;
  12. httpConn=null;
  13. }
  14. else
  15. in.completeReply();
  16. ......
  17. }

这一段主要是把输入流中取得返回值,具体是用AbstractHessianInput包装网络输入流,然后调用AbstractHessianInput.readObject从网络流中反序列化到实际返回值。

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics