原文:Java 動態代理。簡單修改。
靜態代理
創建一個接口,然後創建被代理的類實現該接口並且實現該接口中的抽象方法。之後再創建一個代理類,同時使其也實現這個接口。在代理類中持有一個被代理對象的引用,而後在代理類方法中調用該對象的方法。
接口:
public interface HelloInterface {
void sayHello();
}
被代理類:
public class Hello implements HelloInterface{
@Override
public void sayHello() {
System.out.println("Hello zhanghao!");
}
}
代理類:
public class HelloProxy implements HelloInterface{
private HelloInterface helloInterface = null;
public HelloInterface(HelloInterface o) {
helloInterface = o;
}
@Override
public void sayHello() {
System.out.println("Before invoke sayHello" );
helloInterface.sayHello();
System.out.println("After invoke sayHello");
}
}
代理類調用:
被代理類被傳遞給了代理類 HelloProxy,代理類在執行具體方法時通過所持用的被代理類完成調用。
public static void main(String[] args) {
HelloProxy helloProxy = new HelloProxy(new Hello());
helloProxy.sayHello();
}
Before invoke sayHello
Hello zhanghao!
After invoke sayHello
使用靜態代理很容易就完成了對一個類的代理操作。但是靜態代理的缺點也暴露了出來:由於代理只能爲一個類服務,如果需要代理的類很多,那麼就需要編寫大量的代理類,比較繁瑣。
動態代理
利用反射機制在運行時創建代理類。
接口、被代理類不變,我們構建一個 handler 類來實現 InvocationHandler 接口。
public class ProxyHandler implements InvocationHandler{
private Object object;
public ProxyHandler(Object object){
this.object = object;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("Before invoke " + method.getName());
method.invoke(object, args);
System.out.println("After invoke " + method.getName());
return null;
}
}
使用動態代理:
public static void main(String[] args) {
HelloInterface hello = new Hello();
InvocationHandler handler = new ProxyHandler(hello);
HelloInterface proxyHello = (HelloInterface) Proxy.newProxyInstance(
hello.getClass().getClassLoader(), hello.getClass().getInterfaces(), handler);
proxyHello.sayHello();
}
Before invoke sayHello
Hello zhanghao!
After invoke sayHello
通過 Proxy 類的靜態方法 newProxyInstance 返回一個接口的代理實例。針對不同的代理類,傳入相應的代理程序控制器 InvocationHandler。
如果新來一個被代理類 Bye,如:
public interface ByeInterface {
void sayBye();
}
public class Bye implements ByeInterface {
@Override
public void sayBye() {
System.out.println("Bye zhanghao!");
}
}
那麼執行過程:
public static void main(String[] args) {
HelloInterface hello = new Hello();
ByeInterface bye = new Bye();
InvocationHandler handler = new ProxyHandler(hello);
InvocationHandler handler1 = new ProxyHandler(bye);
HelloInterface proxyHello = (HelloInterface) Proxy.newProxyInstance(
hello.getClass().getClassLoader(), hello.getClass().getInterfaces(), handler);
ByeInterface proxyBye = (ByeInterface) Proxy.newProxyInstance(
bye.getClass().getClassLoader(), bye.getClass().getInterfaces(), handler1);
proxyHello.sayHello();
proxyBye.sayBye();
}
Before invoke sayHello
Hello zhanghao!
After invoke sayHello
Before invoke sayBye
Bye zhanghao!
After invoke sayBye
對於 Hello 和 Bye,能夠使用同一個代理處理器 ProxyHandler 實現代理,是因爲不會直接告訴 ProxyHandler 所代理的類實現了哪些接口,也就是說 ProxyHandler 不依賴於指定接口,這意味着它對被代理類實現了哪些接口一無所知,也不能直接調用某個接口實現類中的方法實現,所以要有一個 Proxy 類,來告知 ProxyHandler 被代理類實現了哪些接口,並間接調用 ProxyHandler 中的代理方法,因爲 Proxy 本身也不知道被代理類實現了哪些接口,所以需要在構造函數中傳入 object.getClass().getInterfaces() 的結果。