老熟女激烈的高潮_日韩一级黄色录像_亚洲1区2区3区视频_精品少妇一区二区三区在线播放_国产欧美日产久久_午夜福利精品导航凹凸

重慶分公司,新征程啟航

為企業提供網站建設、域名注冊、服務器等服務

如何在Java怎么中創建一個動態接口

這篇文章將為大家詳細講解有關如何在Java怎么中創建一個動態接口,文章內容質量較高,因此小編分享給大家做個參考,希望大家閱讀完這篇文章后對相關知識有一定的了解。

創新互聯專業為企業提供中方網站建設、中方做網站、中方網站設計、中方網站制作等企業網站建設、網頁設計與制作、中方企業網站模板建站服務,十載中方做網站經驗,不只是建網站,更提供有價值的思路和整體網絡服務。

1、mybatis / jpa 等orm框架,可以在接口上加注解進行開發,不需要編寫實現類,運行時動態產生實現。

2、dubbo等分布式服務框架,消費者只需要引入接口就可以調用遠程的實現,分析源代碼,其實在消費端產生了接口的代理實現,再由代理調用遠程接口。

3、spring aop 這是最典型的動態代理了。

創建接口的動態實現,有二種最常用的方式:JDK動態代理和CGLIB動態代理。

代理模式是一種常用的設計模式,其目的就是為其他對象提供一個代理以控制對某個真實對象的訪問。

代理類負責為委托類預處理消息,過濾消息并轉發消息,以及進行消息被委托類執行后的后續處理。

如何在Java怎么中創建一個動態接口

通過代理層這一中間層,有效的控制對于真實委托類對象的直接訪問,同時可以實現自定義的控制策略(spring的AOP機制),設計上獲得更大的靈活性。

下面用JDK動態代理加一點簡單的代碼來演示這個過程:

1、接口

package com.yhouse.modules.daos;

public interface IUserDao {
  public String getUserName();
}

2、創建代理

package com.yhouse.modules.daos;

import java.lang.reflect.Proxy;
/**
 * 創建代理
 * @author clonen.cheng
 *
 */
public class Invoker {
  
  
  public Object getInstance(Class<?> cls){    
    MethodProxy invocationHandler = new MethodProxy();    
    Object newProxyInstance = Proxy.newProxyInstance( 
        cls.getClassLoader(), 
        new Class[] { cls }, 
        invocationHandler); 
    return (Object)newProxyInstance;
  }
}

3、運行時調用接口的方法時的實現(這一過程也稱為接口的方法實現)

package com.yhouse.modules.daos;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

public class MethodProxy implements InvocationHandler {

  @Override
  public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {    
    //如果傳進來是一個已實現的具體類(本次演示略過此邏輯)
    if (Object.class.equals(method.getDeclaringClass())) { 
      try { 
        return method.invoke(this, args); 
      } catch (Throwable t) { 
        t.printStackTrace(); 
      } 
    //如果傳進來的是一個接口(核心)
    } else { 
      return run(method, args); 
    } 
    return null;
  }
  
  /**
   * 實現接口的核心方法 
   * @param method
   * @param args
   * @return
   */
  public Object run(Method method,Object[] args){ 
    //TODO     
    //如遠程http調用
    //如遠程方法調用(rmi)
    //....
    return "method call success!";
  } 

}

4、測試

package com.yhouse.modules.daos;

public class ProxyTest {

  
  public static void main(String[] args) {
    IUserDao invoker=(IUserDao)new Invoker().getInstance(IUserDao.class);
    System.out.println(invoker.getUserName());
  }

}

在這段測試代碼中,并沒有接口的任何實現,大家猜猜會是什么結果?

控制臺打印:

如何在Java怎么中創建一個動態接口

說明接口在調用時,把實現委托給了代理,最后具體要做的就是這個代理里面的處理:

如何在Java怎么中創建一個動態接口

在上面這段代碼當中,可以看出,拿到了接口的method以及args,那么就可以做很多的事情,如根據方法名或者配合方法上面的注解來實現比較豐富的功能。

一個簡單的例子只是用來說明這個原理,下面再舉一個遠程接口動態調用的例子來加深理解。

1、創建代理類和目標類需要實現共同的接口Service

package com.markliu.remote.service;
/**
 * Service接口。代理類和被代理類抖需要實現該接口
 */
public interface Service {
  public String getService(String name, int number);
}

2、服務器端創建RemoteService類,實現了Service 接口。

package com.markliu.remote.serviceimpl;
import com.markliu.remote.service.Service;
/**
 * 服務器端目標業務類,被代理對象
 */
public class RemoteService implements Service {
  @Override
  public String getService(String name, int number) {
    return name + ":" + number;
  }
}

3、創建封裝客戶端請求和返回結果信息的Call類

為了便于按照面向對象的方式來處理客戶端與服務器端的通信,可以把它們發送的信息用 Call 類來表示。一個 Call 對象表示客戶端發起的一個遠程調用,它包括調用的類名或接口名、方法名、方法參數類型、方法參數值和方法執行結果。

package com.markliu.local.bean;
import java.io.Serializable;
/**
 * 請求的javabean
 */
public class Call implements Serializable{
  private static final long serialVersionUID = 5386052199960133937L;
  private String className; // 調用的類名或接口名
  private String methodName; // 調用的方法名
  private Class<?>[] paramTypes; // 方法參數類型
  private Object[] params; // 調用方法時傳入的參數值
  /**
   * 表示方法的執行結果 如果方法正常執行,則 result 為方法返回值,
   * 如果方法拋出異常,那么 result 為該異常。
   */
  private Object result;
  public Call() {}
  public Call(String className, String methodName, Class<?>[] paramTypes, Object[] params) {
    this.className = className;
    this.methodName = methodName;
    this.paramTypes = paramTypes;
    this.params = params;
  }
  // 省略了get和set方法
}

4、創建動態代理模式中實際的業務處理類,實現了InvocationHandler 接口

package com.markliu.local.service;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import com.markliu.local.bean.Call;

public class ServiceInvocationHandler implements InvocationHandler {

  private Class<?> classType;
  private String host;
  private Integer port;

  public Class<?> getClassType() {
    return classType;
  }
  public ServiceInvocationHandler(Class<?> classType, String host, Integer port) {
    this.classType = classType;
    this.host = host;
    this.port = port;
  }
  @Override
  public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

    // 封裝請求信息
    Call call = new Call(classType.getName(), method.getName(), method.getParameterTypes(), args);
    // 創建鏈接
    Connector connector = new Connector();
    connector.connect(host, port);
    // 發送請求
    connector.sendCall(call);
    // 獲取封裝遠程方法調用結果的對象
    connector.close();
    Object returnResult = call.getResult();
    return returnResult;
  }
}

5、創建獲取代理類的工廠RemoteServiceProxyFactory

package com.markliu.local.service;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;

/**
 * 動態創建RemoteService代理類的工廠
 */
public class RemoteServiceProxyFactory {

  public static Object getRemoteServiceProxy(InvocationHandler h) {
    Class<?> classType = ((ServiceInvocationHandler) h).getClassType();
    // 獲取動態代理類
    Object proxy = Proxy.newProxyInstance(classType.getClassLoader(), 
        new Class[]{classType}, h);
    return proxy;
  }
}

6、創建底層Socket通信的Connector類,負責創建攔截、發送和接受Call對象

package com.markliu.local.service;
// 省略import

/**
 * 負責創建鏈接
 */
public class Connector {
  private Socket linksocket;
  private InputStream in;
  private ObjectInputStream objIn;
  private OutputStream out;
  private ObjectOutputStream objOut;

  public Connector(){}
  /**
   * 創建鏈接
   */
  public void connect(String host, Integer port) throws UnknownHostException, IOException {
    linksocket = new Socket(host, port);
    in = linksocket.getInputStream();
    out = linksocket.getOutputStream();
    objOut = new ObjectOutputStream(out);
    objIn = new ObjectInputStream(in);
  }
  /**
   * 發送請求call對象
   */
  public void sendCall(Call call) throws IOException {
    objOut.writeObject(call);
  }
  /**
   * 獲取請求對象
   */
  public Call receive() throws ClassNotFoundException, IOException {
    return (Call) objIn.readObject();
  }
  /**
   * 簡單處理關閉鏈接
   */
  public void close() {
    try {
      linksocket.close();
      objIn.close();
      objOut.close();
      in.close();
      out.close();
    } catch (IOException e) {
      e.printStackTrace();
    }
  }
}

7、創建遠程服務器

package com.markliu.remote.main;
// 省略import

public class RemoteServer {

  private Service remoteService;
  public RemoteServer() {
    remoteService = new RemoteService();
  }
  public static void main(String[] args) throws Exception {
    RemoteServer server = new RemoteServer();
    System.out.println("遠程服務器啟動......DONE!");
    server.service();
  }

  public void service() throws Exception {
    @SuppressWarnings("resource")
    ServerSocket serverSocket = new ServerSocket(8001);
    while (true) {
        Socket socket = serverSocket.accept();
        InputStream in = socket.getInputStream();
        ObjectInputStream objIn = new ObjectInputStream(in);
        OutputStream out = socket.getOutputStream();
        ObjectOutputStream objOut = new ObjectOutputStream(out);
        // 對象輸入流讀取請求的call對象
        Call call = (Call) objIn.readObject();
        System.out.println("客戶端發送的請求對象:" + call);
        call = getCallResult(call);
        // 發送處理的結果回客戶端
        objOut.writeObject(call);
        objIn.close();
        in.close();
        objOut.close();
        out.close();
        socket.close();
    }
  }

  /**
   * 通過反射機制調用call中指定的類的方法,并將返回結果設置到原call對象中
   */
  private Call getCallResult(Call call) throws Exception {
    String className = call.getClassName();
    String methodName = call.getMethodName();
    Object[] params = call.getParams();
    Class<?>[] paramsTypes = call.getParamTypes();

    Class<?> classType = Class.forName(className);
    // 獲取所要調用的方法
    Method method = classType.getMethod(methodName, paramsTypes);
    Object result = method.invoke(remoteService, params);
    call.setResult(result);
    return call;
  }
}

8、創建本地客戶端

package com.markliu.local.main;
import java.lang.reflect.InvocationHandler;
import com.markliu.local.service.RemoteServiceProxyFactory;
import com.markliu.local.service.ServiceInvocationHandler;
import com.markliu.remote.service.Service;

public class LocalClient {
  public static void main(String[] args) {
    String host = "127.0.0.1";
    Integer port = 8001;
    Class<?> classType = com.markliu.remote.service.Service.class;
    InvocationHandler h = new ServiceInvocationHandler(classType, host, port);
    Service serviceProxy = (Service) RemoteServiceProxyFactory.getRemoteServiceProxy(h);
    String result = serviceProxy.getService("SunnyMarkLiu", 22);
    System.out.println("調用遠程方法getService的結果:" + result);
  }
}

控制臺打印結果:

如何在Java怎么中創建一個動態接口

這個過程可以簡單的歸納為:本地接口調用(客戶端)--->本地接口代理實現(客戶端)---->遠程實現(服務器端)

關于如何在Java怎么中創建一個動態接口就分享到這里了,希望以上內容可以對大家有一定的幫助,可以學到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。


網站欄目:如何在Java怎么中創建一個動態接口
分享網址:http://www.xueling.net.cn/article/geidei.html

其他資訊

在線咨詢
服務熱線
服務熱線:028-86922220
TOP
主站蜘蛛池模板: 日韩欧美国产视频一区 | 午夜好爽好舒服免费视频 | wwwwxxxx日本| 天堂网在线最新版www | 日本一卡二卡3卡四卡网站精品 | 黄色在线观看www | 久久久久久久片 | 久久99精品久久久久久国产越南 | 日韩高清中文字幕 | 色妺妺在线视频 | 欧美一级片网站 | 男人操女人视频免费观看 | 远方的山楂树免费观看视频48集 | 欧美日韩亚洲国产一区 | 棈品国产乱码久久久久久影片 | 91热播| 亚洲cb精品一区二区三区 | 麻豆91免费 | 免费在线观看国产 | 一本大道一卡二大卡三卡免费 | 国产激情久久久久影院小草 | 国产色婷婷久久99精品91 | 天天干天天操天天插 | www.精品一区 | 青苹果乐园免费高清资源 | 无色福利| 成人亚洲在线观看 | 久久久精品人妻无码专区不卡 | 国产色播av在线 | 一本久久综合亚洲鲁鲁五月天 | 成人深夜小视频 | 国产精品VA在线观看老妇女 | 天天想夜夜操 | 啄木鸟系列在线 | 国产开嫩苞视频在线观看 | 亚洲光棍天堂 | 国产午夜精品一区二区三区小说 | 亚洲精品一线二线三线区别 | 欧美黑人乱大交 | 国产区精品在线观看 | A级毛片无码久久精品免费 激情欧美成人久久综合 |