動態(tài)代理和代理模式有些相似,都是對某個類中的某些方法進行監(jiān)聽,代理模式在這里不多說,下面概括一下動態(tài)代理,以下概括完全是基于個人理解總結的:
動態(tài)代理:在不改變原有類實現(xiàn)的基礎上,通過實現(xiàn)類的接口,對類實現(xiàn)的接口方法的調(diào)用進行監(jiān)聽,實現(xiàn)接口方法調(diào)用前后。0
動態(tài)代理實現(xiàn)方法:
- 定義被代理類的接口方法
- 創(chuàng)建被代理類并實現(xiàn)接口方法
- 創(chuàng)建代理類
- 添加代理
動態(tài)代理的實現(xiàn)
下面我們以對User對象的添加和查找進行代理為例。
User實體對象如下:
public class User {
private String name;
private int age;
public User(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
定義被代理類的接口方法
創(chuàng)建被代理類中代理方法的接口。
public interface IUserControl {
public void addUser(User user);
public User getUser(int index);
}
創(chuàng)建被代理類并實現(xiàn)接口方法
被代理的對象,一定要實現(xiàn)上面定義的接口
public class UserControl implements IUserControl {
private User user;
@Override
public void addUser(User user) {
this.user = user;
}
@Override
public User getUser(int index) {
return this.user;
}
public void delete() {}
}
在上面實體中,有兩種方法的實現(xiàn),一種是接口方法實現(xiàn)(必須有),一種是實體自己的方法(可有可無)。
創(chuàng)建代理類
代理類代碼很少,也非常簡單,先上代碼,然后在說明:
public class UserProxy implements InvocationHandler {
private UserControl control;
private IProxyListener listener;
public UserProxy(UserControl control, IProxyListener listener) {
this.control = control;
this.listener = listener;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object obj;
listener.methoBefor();
obj = method.invoke(control,args);
listener.methodAfter();
return obj;
}
}
代碼雖然不是很多,但是這里很關鍵,不了解的人看了一定會有很多疑問,下面介紹一下這部分代碼。
InvocationHandler 接口
每一個動態(tài)代理類都必須要實現(xiàn)InvocationHandler這個接口,并且每個代理類的實例都關聯(lián)到了一個handler,當我們通過代理對象調(diào)用一個方法的時候,這個方法的調(diào)用就會被轉發(fā)為由InvocationHandler這個接口的 invoke 方法來進行調(diào)用。
看到這里怎么又出來個invoke 方法,下面我們在看看invoke 方法。
invoke 方法
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
我們看到這個方法一共接受三個參數(shù),那么這三個參數(shù)分別代表什么:
proxy: 指代我們所代理的那個真實對象
method: 指代的是我們所要調(diào)用真實對象的某個方法的Method對象
args: 指代的是調(diào)用真實對象某個方法時接受的參數(shù)
看到這里知道上面代碼中為什么obj = method.invoke(control,args);這樣寫了吧,其實不難理解invoke 方法是通過InvocationHandler接口進行調(diào)用的。
添加代理
public class ProxyMain {
public static void main(String[] args) {
UserControl control = new UserControl();
UserProxy proxy = new UserProxy(control, new IProxyListener() {
@Override
public void methoBefor() {
System.out.println("method beford");
}
@Override
public void methodAfter() {
System.out.println("method after");
}
});
IUserControl iUserControl = (IUserControl) Proxy.newProxyInstance(proxy.getClass().getClassLoader(),control.getClass().getInterfaces(),proxy);
iUserControl.addUser(new User("hello",23));
User user = iUserControl.getUser(0);
System.out.println("user:" + user.getName());
}
}
上面代碼依然不是很多,其實關鍵的一行代碼是:
IUserControl iUserControl = (IUserControl) Proxy.newProxyInstance(
proxy.getClass().getClassLoader(),control.getClass().getInterfaces(),proxy);
看到這突然出來了一個Proxy類,Proxy這個類的作用就是用來動態(tài)創(chuàng)建一個代理對象的類的,Proxy 類有好幾個方法,我們常用的就是newProxyInstance方法,通過這個方法名也能知道這個方法是干什么的,這個方法作用是創(chuàng)建一個代理實例的。這個方法有三個參數(shù),下面說明一下:
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)
loader: 一個ClassLoader對象,定義了由哪個ClassLoader對象來對生成的代理對象進行加載
interfaces: 被代理對象實現(xiàn)的接口數(shù)組
h: 一個InvocationHandler對象,實現(xiàn)InvocationHandler接口的代理對象
以上就是動態(tài)代理的實現(xiàn)過程,很簡單吧?。。?/p>
如果上述有錯誤請指出,共同學習,共同進步。