概述
為其他對(duì)象提供一種代理,用以控制對(duì)這個(gè)對(duì)象對(duì)訪問
分類
靜態(tài)代理、動(dòng)態(tài)代理
靜態(tài)代理

AbstractObject接口
public interface IAbstract {
public void operation();
}
ProxyObject 代理類,實(shí)現(xiàn)接口
在代理類里面對(duì)被代理類調(diào)用operation()方法前后可以加更多邏輯限制。
例如:在開發(fā)過程中,想要對(duì)原有的方法做改進(jìn),方法一:直接改原來的方法,方法二:調(diào)用代理類,對(duì)產(chǎn)生的結(jié)果進(jìn)行控制,這就是代理模式
//代理類
public class ProxyI implements IAbstract {
//被代理類對(duì)象
RealI mRealObject;
public ProxyI(RealI mRealObject) {
this.mRealObject = mRealObject;
}
@Override
public void operation() {
if (mRealObject == null) {
mRealObject = new RealI();
}
//在代理類里面對(duì)被代理類調(diào)用operation()方法前后可以加更多邏輯限制。
//例如:在開發(fā)過程中,想要對(duì)原有對(duì)方法做改進(jìn),方法一:直接改原來對(duì)方法,方法二:調(diào)用代理類,對(duì)產(chǎn)生對(duì)結(jié)果進(jìn)行控制,這就是代理模式
mRealObject.operation();
System.out.println("ProxyI: operation()");
}
}
被代理類,同樣實(shí)現(xiàn)接口
//被代理類
public class RealI implements IAbstract {
@Override
public void operation() {
System.out.println("RealI: operation()");
}
}
測(cè)試類
public class ProxyTest {
public static void main(String[] args) {
//
RealI realObject = new RealI();
ProxyI father = new ProxyI(realObject);
father.operation();
}
}
運(yùn)行結(jié)果:

動(dòng)態(tài)代理
什么是動(dòng)態(tài)代理?
代理類是在程序運(yùn)行時(shí)創(chuàng)建的代理方式,代理類他不是在java代碼中定義的,而是程序運(yùn)行時(shí),根據(jù)我們?cè)趈ava代碼中的配置動(dòng)態(tài)生成的。相比于靜態(tài)代理,他可以很方便的對(duì)代理類的函數(shù)進(jìn)行統(tǒng)一處理,而不用頻繁修改每一個(gè)代理類的函數(shù)(根據(jù)你的業(yè)務(wù)邏輯)
- 無侵入式擴(kuò)展代碼: 不修改原來對(duì)代碼情況下,增強(qiáng)方法
jdk動(dòng)態(tài)代理
動(dòng)態(tài)代理的實(shí)現(xiàn):
所要實(shí)現(xiàn)的接口
//所要實(shí)現(xiàn)的接口
public interface ISubject {
void shopping();
}
被代理類
//被代理類
public class Man implements ISubject {
@Override
public void shopping() {
System.out.println("Man :Man Shopping");
}
}
代理類
//代理類
//動(dòng)態(tài)代理的代理類 必須要實(shí)現(xiàn)InvocationHandler接口,并且每個(gè)代理類的實(shí)例都關(guān)聯(lián)到了一個(gè)handler。
//代理對(duì)象調(diào)用程序的時(shí)候,一定要實(shí)現(xiàn)的接口,
// 當(dāng)通過代理對(duì)象調(diào)用方法的時(shí)候,
// 這個(gè)方法就會(huì)把他指派到InvocationHandler的invoke(Object proxy, Method method, Object[] args)上
public class Proxy implements InvocationHandler {
private Object target;//要代理的真實(shí)對(duì)象
public Proxy(Object target) {
this.target = target;
}
//Object proxy: 指代我們所代理的那個(gè)真實(shí)對(duì)象(真實(shí)對(duì)象就是被代理對(duì)象)
//Method method: 指代的是我們所要調(diào)用真實(shí)對(duì)象的某個(gè)方法的Method對(duì)象
//Object[] args: 指代的是調(diào)用真實(shí)對(duì)象某個(gè)方法時(shí)接受的所有參數(shù)
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("proxy :" + proxy.getClass().getName());
System.out.println("proxy :method: " + method);
//在代理真實(shí)對(duì)象前我們可以添加一些自己的操作
System.out.println("proxy :在代理真實(shí)對(duì)象前我們可以添加一些自己的操作");
//當(dāng)代理對(duì)象調(diào)用真實(shí)對(duì)象的方法時(shí),其會(huì)自動(dòng)的跳轉(zhuǎn)到代理對(duì)象關(guān)聯(lián)的handler對(duì)象的invoke方法來進(jìn)行調(diào)用
method.invoke(target, args);
//在代理真實(shí)對(duì)象后我們也可以添加一些自己的操作
System.out.println("proxy :在代理真實(shí)對(duì)象后我們也可以添加一些自己的操作");
return null;
}
}
實(shí)現(xiàn)接口方法
public class ProxyTest {
public static void main(String[] args) {
//被代理者
ISubject man = new Man();
//代理者
Proxy proxy = new Proxy(man);
//首先我們解釋一下為什么我們這里可以將其轉(zhuǎn)化為Subject類型的對(duì)象?
//原因就是在newProxyInstance這個(gè)方法的第二個(gè)參數(shù)上,我們給這個(gè)代理對(duì)象proxy提供了一組什么接口,那么我這個(gè)代理對(duì)象proxy就會(huì)實(shí)現(xiàn)了這組接口,
//這個(gè)時(shí)候我們當(dāng)然可以將這個(gè)代理對(duì)象強(qiáng)制類型轉(zhuǎn)化為這組接口中的任意一個(gè),因?yàn)檫@里的接口是ISubject類型,所以就可以將其轉(zhuǎn)化為ISubject類型了。
ISubject subject = (ISubject) java.lang.reflect.Proxy
.newProxyInstance(man.getClass().getClassLoader(), man.getClass().getInterfaces(), proxy);
System.out.println("ProxyTest " + subject.getClass().getName());
//代理對(duì)象調(diào)用接口方法時(shí),會(huì)關(guān)聯(lián)到InvocationHandler到invoke中的方法去執(zhí)行
subject.shopping();
}
}
InvocationHandler類源碼
public interface InvocationHandler {
//Object proxy: 指代我們所代理的那個(gè)真實(shí)對(duì)象(真實(shí)對(duì)象就是被代理對(duì)象)
//Method method: 指代的是我們所要調(diào)用真實(shí)對(duì)象的某個(gè)方法的Method對(duì)象
//Object[] args: 指代的是調(diào)用真實(shí)對(duì)象某個(gè)方法時(shí)接受的所有參數(shù)
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable;
}
- 在動(dòng)態(tài)代理中,每個(gè)代理類的對(duì)象都會(huì)關(guān)聯(lián)一個(gè)表示內(nèi)部處理邏輯都InvocationHandler接口的實(shí)現(xiàn),當(dāng)我們調(diào)用了代理對(duì)象所代理的接口中的方法的時(shí)候,這個(gè)方法的調(diào)用就會(huì)被轉(zhuǎn)發(fā)到InvocationHandler這個(gè)接口的 invoke 方法來進(jìn)行調(diào)用。
- invoke方法的參數(shù)可以獲?。?/li>
- 所代理的真實(shí)對(duì)象(被代理對(duì)象)、
- 所要調(diào)用的真實(shí)對(duì)象的方法、
- 所要調(diào)用的真實(shí)對(duì)象的方法的參數(shù)
- invoke()返回值返回給我們使用者
newProxyInstance
java.lang.reflect.Proxy作用是動(dòng)態(tài)創(chuàng)建一個(gè)對(duì)象的類,他提供了很多方法我們用的最多的就是 newProxyInstance 這個(gè)方法
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
throws IllegalArgumentException {
Objects.requireNonNull(h);
final Class<?>[] intfs = interfaces.clone();
/*
* Look up or generate the designated proxy class.
*/
Class<?> cl = getProxyClass0(loader, intfs);
try {
final Constructor<?> cons = cl.getConstructor(constructorParams);
final InvocationHandler ih = h;
if (!Modifier.isPublic(cl.getModifiers())) {
cons.setAccessible(true);
}
return cons.newInstance(new Object[]{h});
} catch (IllegalAccessException | InstantiationException e) {
throw new InternalError(e.toString(), e);
} catch (InvocationTargetException e) {
Throwable t = e.getCause();
if (t instanceof RuntimeException) {
throw (RuntimeException) t;
} else {
throw new InternalError(t.toString(), t);
}
} catch (NoSuchMethodException e) {
throw new InternalError(e.toString(), e);
}
}
動(dòng)態(tài)代理總結(jié)
調(diào)用java.lang.reflect.Proxy類的newProxyInstanced(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h)方法,他會(huì)根據(jù)我們傳遞來的class對(duì)象,生成一個(gè)代理類,每當(dāng)代理類執(zhí)行接口方法的時(shí)候,就會(huì)調(diào)用InvocationHandler里面的invoke(Object proxy, Method method, Object[] args)方法,在invoke方法中可以執(zhí)行想要的操作,這就是動(dòng)態(tài)代理。
注意??:
- 代理類他不是在java代碼中手動(dòng)碼的代碼,而是程序運(yùn)行時(shí),根據(jù)我們?cè)趈ava代碼中的配置動(dòng)態(tài)生成的
- 代理類實(shí)現(xiàn)InvocationHandler接口
- 反射包中的java.lang.reflect.Proxy類newProxyInstance()創(chuàng)建動(dòng)態(tài)代理
- 動(dòng)態(tài)代理與靜態(tài)代理最大的不同:動(dòng)態(tài)代理代理類不需要手動(dòng)生成,是運(yùn)行時(shí)候動(dòng)態(tài)生成,根據(jù)我們?cè)趈ava代碼中的配置在運(yùn)行期動(dòng)態(tài)生成的,這個(gè)動(dòng)態(tài)生成的代理類,已經(jīng)實(shí)現(xiàn)了代理中的相關(guān)接口。
CFLIB動(dòng)態(tài)代理
CGLIB(Code Generation Library)是一個(gè)開源項(xiàng)目!是一個(gè)強(qiáng)大的,高性能,高質(zhì)量的Code生成類庫(kù),它可以在運(yùn)行期擴(kuò)展Java類與實(shí)現(xiàn)Java接口。Hibernate用它來實(shí)現(xiàn)PO(Persistent Object 持久化對(duì)象)字節(jié)碼的動(dòng)態(tài)生成。詳解有待更新。