當我們需要呼叫某個類別(具體實現類別)的方法時,不直接建立該類別的對象,而是拿到該類別的代理類別對象,透過代理對象,呼叫具體實現類別的功能。具體實作類別和代理類別都實作同樣的接口,並且代理類別持有實作類別的物件。這樣做在呼叫端和具體實作端,做了一層隔離,避免直接打交道。
代理模式在現實中也有很多類似的例子,例如我們買房租房,都得透過中介,這個中介就相當於代理。
1)定義介面:
public interface IHouse { void sallHouse(); int sallHouse2(); }
2)具體實作類別:
public class Andy implements IHouse { @Override public void sallHouse() { System.out.println("andy sall house.."); } @Override public int sallHouse2() { return 100; } }
3)代理程式類別:
public class HouseProxy implements IHouse { Andy andy; public HouseProxy(Andy andy) { this.andy = andy; } @Override public void sallHouse() { andy.sallHouse(); } @Override public int sallHouse2() { return andy.sallHouse2(); } }
4)客戶端呼叫:
//1.创建被代理对象 Andy andy = new Andy(); //2.创建代理对象,代理对象持有被代理对象的引用 HouseProxy proxy = new HouseProxy(andy); //3.客户端通过代理对象调用。 proxy.sallHouse();
//1.被代理对象 final Andy andy = new Andy(); //2.创建动态代理,Java在运行时动态生成的。 ClassLoader classLoader = andy.getClass().getClassLoader(); Class[] interfaces = andy.getClass().getInterfaces(); IHouse iHouse = (IHouse) Proxy.newProxyInstance(classLoader, interfaces, new InvocationHandler() { @Override public Object invoke(Object o, Method method, Object[] objects) throws Throwable { //通过反射调用被代理对象的方法 return method.invoke(andy, objects); } }); //3.客户端通过代理对象调用被代理方法。 iHouse.sallHouse();
動態代理程式分析:
1)IHouse iHouse = (IHouse) Proxy.newProxyInstance();
建立動態代理對象,
有三個參數:
1.ClassLoader 類別載入器
2.被代理介面的Class類,
3.InvocationHandler介面實作類別
2)拿到iHouse動態代理後,呼叫介面的方法iHouse.sallHouse();
這個方法一被調用,就會執行InvocationHandler類別中invoke方法。
@Override
public Object invoke(Object o, Method method, Object[] objects) throws Throwable {
//透過反射呼叫被代理物件的方法
return method.invoke(andy, objects);
}
invoke方法有三個參數:
method,就是代理類呼叫的方法名稱(sallHouse)
objects,就是代理類別呼叫方法時傳遞的參數。
Object obj = method.invoke(andy, objects);
透過反射機制 呼叫andy對象,具體實現者中對應的方法。
他的回傳值,可以在代理物件呼叫介面時接收,是什麼類型,就回傳什麼類型。 Retrofit就是這樣做的
以上是Java動態代理程式是什麼及怎麼實現的詳細內容。更多資訊請關注PHP中文網其他相關文章!