代理模式是常用的Java設計模式,它的特徵是代理類與委託類有同樣的接口,一個代理類的對象與一個委託類的對象關聯,代理類的對象本身並不真正實現服務,而是通過調用委託類的對象的相關方法,來提供特定的服務,代理類主要負責爲委託類預處理消息、過濾消息、把消息轉發給委託類,以及事後處理消息等。
簡單舉個例子,例如你現在正在看電視,但是老師佈置了作業,你又想看電視又要完成作業,你靈機一動,讓哥哥幫你寫,你開心的看完電視,作業也寫完了,這種讓別人代替你完成的某種任務的行爲就是代理模式
按照代理類的創建時期,代理類可分爲兩種。
靜態代理:
由程序員創建或由特定工具自動生成源代碼,再對其編譯。在程序運行前,代理類的.class文件就已經存在了。實現類和代理類實現同一個接口,將實現類對象傳遞給代理類,代理類的實現方法實際是由實現類完成操作的。
public interface Subject {
void visit();
}
//執行者,代理者
public class RealSubject implements Subject {
private String name = "proxy";
@Override
public void visit() {
System.out.println(name);
}
}
//委託者,被代理者
public class ProxySubject implements Subject{
private Subject subject;
public ProxySubject(Subject subject) {
this.subject = subject;
}
@Override
public void visit() {
subject.visit();
}
}
//執行
public class Client {
public static void main(String[] args) {
//真正執行的是代理者
ProxySubject subject = new ProxySubject(new RealSubject());
subject.visit();
}
}
動態代理
動態代理有別於靜態代理,是根據代理的對象,動態創建代理類。這樣,就可以避免靜態代理中代理類接口過多的問題。動態代理是實現方式,是通過反射來實現的,藉助Java自帶的java.lang.reflect.Proxy,通過固定的規則生成。
其步驟如下:
- 編寫一個委託類的接口,即靜態代理的(Iuser接口)
- 實現一個真正的委託類,即靜態代理的(UserImpl類)
- 創建一個動態代理類,實現InvocationHandler接口,並重寫該invoke方法
在測試類中,生成動態代理的對象。
第一二步驟,和靜態代理一樣,不過說了。第三步,代碼如下:
動態代理Demo
public interface Iuser {
void eat(String s);
}
//委託類,執行者
public class UserImpl implements Iuser {
@Override
public void eat(String s) {
System.out.println("我要喫"+s);
}
}
public class DynamicProxy implements InvocationHandler {
private Object object;//用於接收具體實現類的實例對象
//使用帶參數的構造器來傳遞具體實現類的對象
public DynamicProxy(Object obj){
this.object = obj;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)throws Throwable {
Object result = method.invoke(object, args);
return result;
}
}
public class ProxyTest {
public static void main(String[] args) {
Iuser user = new UserImpl();
InvocationHandler h = new DynamicProxy(user);
Iuser proxy = (Iuser) Proxy.newProxyInstance(user..getClass().getClassLoader(), new Class[]{Iuser.class}, h);
proxy.eat("蘋果");
}
}
創建動態代理的對象,需要藉助Proxy.newProxyInstance。該方法的三個參數分別是:
- ClassLoader loader表示當前使用到的appClassloader。
- Class<?>[] interfaces表示目標對象實現的一組接口。
- InvocationHandler h表示當前的InvocationHandler實現實例對象。
簡單介紹了 靜態代理和動態代理的區別