代理物件
代理
是一種設計模式,他提供了對目標物件的一種訪問方式(通過代理物件去訪問目標物件)
使用的編程思想
不要隨意去修改別人已經寫好的代碼或者方法,如果需改修改,可以通過代理的方式來擴展該方法
最基本的例子
如果你要邀請一個明星來參加活動,你要聯系明星的經紀人而不是聯系明星本人來達到同樣的目的,明星是咱們的目標物件,他是要來參加活動中的節目,剩下的其他事情都是他的經紀人來處理
代理模式的關鍵點是
代理物件與目標物件.代理物件是對目標物件的擴展,并會呼叫目標物件
靜態代理
靜態代理在使用時,需要定義介面或者父類,目標物件與代理物件一起實作相同的介面或者是繼承相同父類.
好處:
在目標物件的基礎上增加額外的功能操作,
缺點:
因為代理物件需要與目標物件實作一樣的介面,所以會有很多代理類,類太多.同時,一旦介面增加方法,目標物件與代理物件都要維護.
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();
}
}
運行結果

轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/41694.html
標籤:java
