代理對象
代理
是一種設計模式,他提供了對目标對象的一種通路方式(通過代理對象去通路目标對象)
使用的程式設計思想
不要随意去修改别人已經寫好的代碼或者方法,如果需改修改,可以通過代理的方式來擴充該方法
最基本的例子
如果你要邀請一個明星來參加活動,你要聯系明星的經紀人而不是聯系明星本人來達到同樣的目的,明星是咱們的目标對象,他是要來參加活動中的節目,剩下的其他事情都是他的經紀人來處理
代理模式的關鍵點是
代理對象與目标對象.代理對象是對目标對象的擴充,并會調用目标對象
靜态代理
靜态代理在使用時,需要定義接口或者父類,目标對象與代理對象一起實作相同的接口或者是繼承相同父類.
好處:
在目标對象的基礎上增加額外的功能操作。
缺點:
因為代理對象需要與目标對象實作一樣的接口,是以會有很多代理類,類太多.同時,一旦接口增加方法,目标對象與代理對象都要維護.
public interface IUserDao {
public void save();
}
/**
*
* 接口實作
* 目标對象
*
*/
public class UserDao implements IUserDao {
@Override
public void save() {
System.out.println("明星參加活動做節目");
}
}
/**
*
* 實作接口
* 代理對象,靜态代理
*
*/
public class UserDaoProxy implements IUserDao{
private IUserDao target;
public UserDaoProxy(IUserDao target) {
this.target = target;
}
@Override
public void save() {
System.out.println("活動之前經紀人處理瑣碎的事情");
target.save();
System.out.println("活動之後經紀人處理瑣碎的事情");
}
}
public class ProxyTest {
public static void main(String[] args) {
//目标對象
UserDao target = new UserDao();
//代理對象
UserDaoProxy userDaoProxy = new UserDaoProxy(target);
//執行的是代理的方法
userDaoProxy.save();
}
}
運作結果
動态代理
特點:
- 代理對象,不需要實作接口
- 代理對象的生成,是利用JDK的API,動态的在記憶體中建構代理對象(需要我們指定建立代理對象/目标對象實作的接口的類型)
- 動态代理也叫做:JDK代理,接口代理
JDK中生成代理對象的API
代理類所在包:java.lang.reflect.Proxy
JDK實作代理隻需要使用newProxyInstance方法,但是該方法需要接收三個參數,完整的寫法是:
static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces,InvocationHandler h )
/*
注意該方法是在Proxy類中是靜态方法,且接收的三個參數依次為:
ClassLoader loader,:指定目前目标對象使用類加載器,擷取加載器的方法是固定的
Class<?>[] interfaces,:目标對象實作的接口的類型,使用泛型方式确認類型
InvocationHandler h:事件處理,執行目标對象的方法時,會觸發事件處理器的方法,會把目前執行目标對象的方法作為參數傳入
*/
注意
代理對象不需要實作接口,但是目标對象一定要實作接口,否則不能用動态代理
public interface IUserDao {
public void save();
}
/**
*
* 接口實作
* 目标對象
*
*/
public class UserDao implements IUserDao {
@Override
public void save() {
System.out.println("明星參加活動做節目");
}
}
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class ProxyFactory {
//維護一個目标對象
private Object target;
public ProxyFactory(Object target){
this.target=target;
}
//給目标對象生成代理對象
public Object getProxyInstance(){
return Proxy.newProxyInstance(
target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("活動之前經紀人處理瑣碎的事情");
//執行目标對象方法
Object returnValue = method.invoke(target, args);
System.out.println("活動結束後經紀人處理瑣碎的事情");
return returnValue;
}
}
);
}
}
public class DHCPProxyTest {
public static void main(String[] args) {
// 目标對象7
IUserDao target = new UserDao();
//原始的類型 class com.rsw.DHCPproxy.dao.UserDaoo
System.out.println(target.getClass());
// 給目标對象,建立代理對象
IUserDao proxy = (IUserDao) new ProxyFactory(target).getProxyInstance();
// class com.sun.proxy.$Proxy0 記憶體中動态生成的代理對象
System.out.println(proxy.getClass());
// 執行方法執行的是代理對象的方法!
proxy.save();
}
}
運作結果
代碼打包