一、什麼叫jdk的代理?
用另外一個物件去代理實際物件的操作
分為動態代理和靜態代理
二、先說說靜態代理
從字面意思來看就是不會改變的,只可以代理某個固定物件的。
靜態代理就是通過實現和目標物件實現的同一個介面來代理目標物件。
通俗一點:例如A類實現了B介面,這時候我們要代理A類,我們需要宣告一個C類也實現B介面,從而達到代理A類的目的;這個時候我們操作A類的方法時,可以通過操作C類來實現。
看程式碼:
1、寫一個介面
public interface MyTest02 { void test01(String a); }
2、寫一個類實現這個介面
public class MyTest03 implements MyTest02 { @Override public void test01(String a) { System.out.println(123); } }
3、寫一個類來代理
public class MyTest04 implements MyTest02{ private MyTest03 myTest03; public MyTest04(MyTest03 myTest03){ this.myTest03=myTest03; } @Override public void test01(String a) { System.out.println("處理前"); myTest03.test01(a); System.out.println("處理後"); } }
4、編寫測試類
public class MainTest { public static void main(String[] args) { MyTest03 myTest03 = new MyTest03(); /* MyTest01 test01 = new MyTest01(myTest03); MyTest02 subject = (MyTest02) Proxy.newProxyInstance(MyTest03.class.getClassLoader(), MyTest03.class.getInterfaces(), test01); subject.test01("456");*/ MyTest04 test04 = new MyTest04(myTest03); test04.test01(""); } }
5、執行結果
6、靜態代理總結:
可以在不操作原物件的同時新增前置方法和後置方法,不需要操作原物件的同時更改邏輯,這也是唯一的優點哈,可以說是沒有優點!因為需要代理一個類時就需要寫一個實現類,一般都是用接下來要說的動態代理!
三、動態代理
靜態代理可以實現的功能,動態代理都可以實現!動態代理的實現是在執行時,根據一組介面定義,使用Proxy、InvocationHandler等工具類去生成一個代理類和代理類例項。
相比於靜態代理來說,動態代理需要代理一個類的時候不需要額外寫一個實現類;大部分的工作都是Proxy工具類幫我們完成的。
看程式碼:
1、基於上面的程式碼,寫一個類實現InvocationHandler
import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; public class MyTest01 implements InvocationHandler { private Object subject; /** * 構造方法,給我們要代理的真實物件賦初值 * * @param subject */ public MyTest01(Object subject) { this.subject = subject; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { //在代理真實物件前我們可以新增一些自己的操作 System.out.println("在呼叫之前,我要乾點啥呢?"); System.out.println("Method:" + method); //當代理物件呼叫真實物件的方法時,其會自動的跳轉到代理物件關聯的handler物件的invoke方法來進行呼叫 Object returnValue = method.invoke(subject, args); //在代理真實物件後我們也可以新增一些自己的操作 System.out.println("在呼叫之後,我要乾點啥呢?"); return returnValue; } }
2、測試類;例如我要代理String這個類從介面CharSequence實現過來的.length()方法
import java.lang.reflect.Proxy;
public class MainTest {
public static void main(String[] args) {
String myTest03 = new String("123");
MyTest01 test01 = new MyTest01(myTest03);
CharSequence subject = (CharSequence) Proxy.newProxyInstance(String.class.getClassLoader(), String.class.getInterfaces(), test01);
System.out.println(subject.length());
}
}
3、執行結果
4、動態代理總結:
要使用jdk的代理功能的話,一般都是使用的動態代理,動態代理和靜態代理都需要實現介面才可以進行代理;主要用於新增目標方法邏輯時,又不想改變原代的時候;
如果沒有實現介面又想使用代理功能的話,可以去看看cglib動態代理。