靜態代理和動態代理主要解決的問題是:在直接訪問對象時帶來的問題,其目的就是為其他對象提供一個代理以控制對某個對象的訪問。代理類負責為委托類預處理消息,過濾消息並轉發消息,以及進行消息被委托類執行后的后續處理。
靜態代理在感覺上和裝飾設計模式很像
1)、在代理類中實現被代理類實現的所有接口,這樣保證了被代理類所能實現的方法,代理類也能實現,保證了兩邊行為的一致性,代理類就能轉型為被代理類,當作被代理類處理。而代理中有被代理類的對象,這樣,在代理類的內部實現接口方法時就能調用被代理類的方法,從而進行對被代理類的封裝。
簡單的示范:
package cn.edu.cjl;
public interface Subject {
public void replace();
}
package cn.edu.cjl;
public class RealSubject implements Subject{
@Override
public void replace() {
// TODO Auto-generated method stub
System.out.println("real subject...");
}
}
package cn.edu.cjl;
public class daili implements Subject {
RealSubject subject;
@Override
public void replace() {
System.out.println("before...");
if(subject==null){
subject=new RealSubject();
}
subject.replace();
System.out.println("after...");
}
}
package cn.edu.cjl;
public class Client {
public static void main(String[] args) {
Subject subject=new daili();
subject.replace();
}
}
代碼中定義接口Subject,真實的實現類是RealSubject,但是在在主方法中調用的是daili類,在daili類中同樣實現了Subject接口,但是真實上調用的是RealSubject類的方法。這就是靜態代理。
靜態代理可以解決直接訪問類方法帶來的問題,但是本身也有問題,就是當大量的使用靜態代理時類的個數將雙倍的增加,不利於程序的管理。
動態代理使用了反射技術,一個代理類可以為任意類提供代理。
代理類必須實現InvocationHandler接口,對代理實例調用方法時,將對方法調用進行編碼並將其指派到它的代理程序的 invoke 方法。
invoke方法運用反射技術,通過java.lang.reflect.Proxy類中提供的靜態方法 newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) 返回一個指定接口的代理類實例,該接口可以將方法調用指派到指定的調用處理程序,也就是代理類實現的InvocationHandler接口中的invoke方法中,這個方法的各個參數的意思是
ClassLoader loader:類加載器,定義代理類的類加載器,可以任意指定。
Class<?>[] interfaces: 被代理類所實現的所有接口的class數組,可以用class對象的getInterfaces()方法得到。
InvocationHandler h:實現了InvocationHandler接口的對象。
簡單的事例:
package cn.edu.cjl.proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class proxy implements InvocationHandler {
private Object object;
public proxy(Object obj){
this.object=obj;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
System.out.println("before");
Object resultObject= method.invoke(object, args);
System.out.println("after");
return resultObject;
}
}
package cn.edu.cjl.proxy;
import java.lang.reflect.Proxy;
public class Client {
public static void main(String[] args) {
Subject subject = null;
RealSubject rSubject = new RealSubject();
proxy proxy = new proxy(rSubject);
subject = (Subject) Proxy.newProxyInstance(Client.class
.getClassLoader(), rSubject.getClass().getInterfaces(), proxy);
subject.replace();
}
}
