Java靜態代理與動態代理
1.靜態代理(通過接口實現類去代理另一個接口實現類)
- 解釋:靜態代理就比如租房這個事件,房東是真實對象,中介是代理對象,我是客戶,我要去找中介才能租房子(比自己找更方便,還有中介服務)。房東實現租房接口能出租房子,中介實現租房接口也能出租房子,但是房子是房東的,中介只能代理,於是中介只能靠房東(真實對象)實現出租房子,當然中介還可以加上其它自己想要的操作
- 例子:
租房接口:
package com.lxf.demo01;
//租房接口
public interface Rent {
public void rent();
}
房東(真實對象):
package com.lxf.demo01;
//房東對象
public class Host implements Rent{
@Override
public void rent() {
System.out.println("房東要出租房子");
}
}
中介(代理對象)
package com.lxf.demo01;
public class Proxy implements Rent{
private Host host;
public Proxy() {
}
//將真實對象賦給host
public setHost(Host host) {
this.host = host;
}
@Override
public void rent() {
//看房子
seeHouse();
//籤合同
singContract();
//出租房子
host.rent();
//收費
fare();
}
//看房
public void seeHouse(){
System.out.println("中介帶你看房");
}
//收中介費
public void fare(){
System.out.println("中介收中介費");
}
//籤合同
public void singContract(){
System.out.println("籤租賃合同");
}
}
客戶(測試實例):
package com.lxf.demo01;
public class Client {
public static void main(String[] args) {
//房東:真實對象
Host host=new Host();
//代理:代理對象
Proxy proxy = new Proxy();
//將真實對象傳給代理對象
proxy.setHost(Host host);
//找中介租房(中介在中間撈油水)
proxy.rent();
}
}
2.動態代理
- 解釋:再次看租房這個事件,房東是真實對象,中介是代理對象,我是客戶,我要去找中介才能租房子。房東實現租房接口能出租房子,此時中介不實現租房接口,建一個生成代理類的類(通過set或者構造函數接收真實對象,生成代理類),生成代理類的類實現InvocationHandler接口,然後將房東丟入生成代理類的類生成中介代理類,這個於是中介代理類就可以出租房子了,當然中介還可以加上其它自己想要的操作
- 例子:
租房接口:
package com.lxf.demo01;
//租房接口
public interface Rent {
public void rent();
}
房東接口:
package com.lxf.demo01;
//房東對象
public class Host implements Rent{
@Override
public void rent() {
System.out.println("房東要出租房子");
}
}
生成代理類的類:
package com.lxf.demo03;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
//實現代理類生成的類
public class ProxyInvocationHandler implements InvocationHandler {
//被代理的真實對象
private Rent rent;
//設置真實對象
public void setRent(Rent rent) {
this.rent = rent;
}
//生成代理類
public Object getProxy(){
//Proxy.newProxyInstance(ClassLoader loader,Class<?>[] Ingterfaces,InvocationHandler h);
//第一個參數:真實對象的類加載器
//第二個參數:真實對象實現的所有的接口
//第三個參數: 接口,傳遞一個匿名內部類對象
return Proxy.newProxyInstance(rent.getClass().getClassLoader(),
rent.getClass().getInterfaces(),this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//動態代理的本質:使用反射機制實現!
//實現方法
Object result = method.invoke(rent, args);
return result;
}
}
客戶(測試實例):
package com.lxf.demo03;
public class Client {
public static void main(String[] args) {
//真實角色
Host host = new Host();
//獲取代理角色的類
ProxyInvocationHandler handler = new ProxyInvocationHandler();
//將真實角色加入
handler.setRent(host);
//代理角色
Rent proxy = (Rent) handler.getProxy();
//實現方法
proxy.rent();
}
}
3.靜態代理與動態代理異同
-
相同處:都是通過代理對象去實現方法,並且都可以加上其它操作。
-
不同處:靜態代理是通過代理對象實現類去代理真實對象實現類,而動態代理是通過一個生成代理類的類去生成代理對象,動態代理的好處在於"很靈活"。靜態代理的代理對象是一個實際的類,要是真實對象發生改變,代理對象也要改。而動態代理的代理對象通過類產生,而不完全依賴於類,當真實對象發生改變也沒事,甚至可以將生成代理類的類改成萬能類:
package com.lxf.demo04; import com.lxf.demo03.Rent; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; //實現代理類生成的類 public class ProxyInvocationHandler implements InvocationHandler { //被代理的接口 private Object target; public void setTarget(Object target) { this.target = target; } //生成代理類 public Object getProxy(){ return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(),this); } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println(method.getName()); //動態代理的本質:使用反射機制實現! Object result = method.invoke(target, args); return result; } }
動態代理分類補充:
- 基於接口:jdk動態代理類
- 基於類:cglib動態代理類
- java字節碼實現:javassist(用在JBoss服務器上)