靜態(tài)代理
靜態(tài)代理是代理模式的實(shí)現(xiàn)方式之一,是相對(duì)于動(dòng)態(tài)代理而言的。所謂靜態(tài)代理是指,在程序運(yùn)行前,由程序員創(chuàng)建或特定工具自動(dòng)生成源代碼并對(duì)其編譯生成.class文件。
靜態(tài)代理的實(shí)現(xiàn)只需要三步:首先,定義業(yè)務(wù)接口;其次,實(shí)現(xiàn)業(yè)務(wù)接口;然后,定義代理類并實(shí)現(xiàn)業(yè)務(wù)接口;最后便可通過(guò)客戶端進(jìn)行調(diào)用。
/**
* 代理接口
*/
public interface DemoService {
public void print(String param);
}
/**
* 真正的實(shí)現(xiàn)類
*/
public class DemoServiceImpl implements DemoService {
@Override
public void print(String param) {
System.out.println("real method:" + param);
}
}
/**
* 代理類
*/
public class DemoProxy implements DemoService {
private DemoService demoService;
public DemoProxy(DemoServiceImpl impl) {
this.demoService = impl;
}
@Override
public void print(String param) {
System.out.println("before real method");
demoService.print("AAA");
System.out.println("after real method");
}
}
//測(cè)試類
public class Test {
public static void main(String[] args) {
DemoService demoService = new DemoProxy(new DemoServiceImpl());
demoService.print("AAA");
}
}

靜態(tài)代理的局限性:
一個(gè)代理類Proxy只能服務(wù)Subject一種接口,如果有10個(gè)不同類型的對(duì)象,需要?jiǎng)?chuàng)建10個(gè)代理類,類的數(shù)量激增、也增加了代碼的冗余
如果只用一個(gè)代理類,就能完成全部的代理功能就好了,于是就有了動(dòng)態(tài)代理
動(dòng)態(tài)代理
和靜態(tài)代理不同,動(dòng)態(tài)代理的字節(jié)碼是在程序運(yùn)行期間,由JVM根據(jù)反射等機(jī)制動(dòng)態(tài)生成的。代理類和實(shí)際類的關(guān)系是在程序運(yùn)行時(shí)確定的,依托反射等機(jī)制,動(dòng)態(tài)代理可以動(dòng)態(tài)生成任意類型的代理類,一個(gè)代理的處理程序就可以處理多種對(duì)象。
java中的動(dòng)態(tài)代理有兩種,一種是java自帶的jdk動(dòng)態(tài)代理,一種是基于cglib的動(dòng)態(tài)代理
JDK動(dòng)態(tài)代理
(1)Proxy 類提供了用于創(chuàng)建動(dòng)態(tài)代理類和實(shí)例對(duì)象的方法,它是所創(chuàng)建的動(dòng)態(tài)代理類的父類
(2)InvocationHandler 接口是代理處理程序類的實(shí)現(xiàn)接口,每一個(gè)被生成的代理類實(shí)例都可以提供一個(gè)相關(guān)的代理處理程序類,代理類實(shí)例的方法被調(diào)用時(shí)會(huì)回調(diào)invoke()方法
public interface DemoService {
public String print(String param);
}
public class DemoServiceImpl implements DemoService {
@Override
public String print(String param) {
System.out.println("REAL Method");
return param + " REAL METHOD";
}
}
public class ProxyHandler implements InvocationHandler {
private Object obj;
public ProxyHandler(Object obj) {
this.obj = obj;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("before Real Method");
String print = (String)method.invoke(obj, args);
System.out.println("after Real Method");
return print;
}
}
public class Test {
public static void main(String[] args) {
DemoServiceImpl impl = new DemoServiceImpl();
ProxyHandler handler = new ProxyHandler(impl);
DemoService demo = (DemoService) Proxy.newProxyInstance(impl.getClass().getClassLoader(),
impl.getClass().getInterfaces(), handler);
demo.print("AAAA");
}
}

JDK動(dòng)態(tài)代理的局限性:如果是抽象類或者一般的類需要進(jìn)行代理,jdk動(dòng)態(tài)代理就無(wú)法滿足了,只有使用cglib動(dòng)態(tài)代理
cglib動(dòng)態(tài)代理
主要用到import net.sf.cglib.proxy包下的MethodInterceptor、MethodProxy和Enhancer類
(1)、MethodInterceptor
MethodInterceptor類是方法攔截器,代理類實(shí)例的方法被調(diào)用時(shí)會(huì)回調(diào)MethodInterceptor的intercept()方法攔截,用來(lái)實(shí)現(xiàn)自己的代理邏輯,類似于jdk動(dòng)態(tài)代理的InvocationHandler接口
(2)、MethodProxy
MethodProxy是intercept()方法中的第四個(gè)參數(shù)的類型,它是實(shí)際類方法的代理引用,使用methodProxy比使用jdk自身的method在效率上會(huì)有提升
(3)、Enhancer
Enhancer用來(lái)動(dòng)態(tài)創(chuàng)建實(shí)際類子類的代理類實(shí)例,setSuperclass()方法設(shè)置實(shí)際類為父類,setCallback()方法建立方法回調(diào),create()方法創(chuàng)建一個(gè)代理類實(shí)例
public class RealDemo {
public void print(String param) {
System.out.println("REAL METHOD " + param);
}
}
public Object newInstance(Object target) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(target.getClass());
enhancer.setCallback(this);
return enhancer.create();
}
@Override
public Object intercept(Object arg0, Method mrthod, Object[] arg2, MethodProxy proxy) throws Throwable {
System.out.println("BEFORE......");
Object object = proxy.invokeSuper(arg0, arg2);
System.out.println("AFTER......");
return object;
}
}
public class Test {
public static void main(String[] args) {
RealDemo demo = new RealDemo();
ProxyIntercept intercept = new ProxyIntercept();
RealDemo proxyDemo = (RealDemo) intercept.newInstance(demo);
proxyDemo.print("AAA");
}
}
jdk動(dòng)態(tài)代理是由java內(nèi)部的反射機(jī)制生成一個(gè)實(shí)現(xiàn)代理接口的匿名類,被代理的類必須要實(shí)現(xiàn)一個(gè)接口,如果某個(gè)類沒(méi)有實(shí)現(xiàn)接口則不能生成代理對(duì)象,實(shí)際使用中會(huì)有一些局限性
cglib動(dòng)態(tài)代理底層是借助asm來(lái)實(shí)現(xiàn)的,加載實(shí)際類的.class文件,修改其字節(jié)碼生成子類來(lái)處理,比java反射效率要高一些,不過(guò)生成子類的方式也帶來(lái)小問(wèn)題:目標(biāo)類不能聲明成final,因?yàn)閒inal類不能被繼承,無(wú)法生成代理;目標(biāo)方法也不能聲明成final,final方法不能被重寫,無(wú)法得到處理
參考:https://blog.csdn.net/justloveyou_/article/details/79407248
https://www.cnblogs.com/ctxsdhy/p/5815492.html