Java開發雜談(八)代理
阿新 • • 發佈:2019-01-03
1、代理簡介
代理分為靜態代理和動態代理,靜態代理實現簡單,動態代理功能更加強大。靜態代理是AOP框架會在編譯階段生成AOP代理類,因此稱為編譯時增強。動態代理是執行時增強,AOP框架不會去修改位元組碼,而是在記憶體中臨時為方法生成一個AOP物件,這個AOP物件包含了目標物件的全部方法,並且在特定的切點做了增強處理,並回調原物件的方法。
動態代理有兩種實現,jdk動態代理和cglib代理:
jdk動態代理的原理是實現介面的例項,攔截定於介面中的目標方法,效能更優,是spring生成代理的優先選擇。缺點是隻能代理實現了介面的類,沒有實現介面的類不能實現JDK動態代理。
cglib代理的原理是使用cglib庫中的位元組碼動態生成技術,生成被代理類的子類例項,可以攔截代理類中的任一public方法的呼叫,無論目標方法是否定義與介面中,更通用,但效能相對jdk代理差一些。
2、JDK動態代理實現
// 動態代理類 public class DynamicProxy implements InvocationHandler { // 這個就是我們要代理的真實物件 private Object subject; // 構造方法,給我們要代理的真實物件賦初值 public DynamicProxy(Object subject) { this.subject = subject; } @Override public Object invoke(Object object, Method method, Object[] args) throws Throwable { // 在代理真實物件前我們可以新增一些自己的操作 System.out.println("before rent house"); System.out.println("Method:" + method); // 當代理物件呼叫真實物件的方法時,其會自動的跳轉到代理物件關聯的handler物件的invoke方法來進行呼叫 method.invoke(subject, args); // 在代理真實物件後我們也可以新增一些自己的操作 System.out.println("after rent house"); return null; } }
// Client類 public class Client { public static void main(String[] args) { // 我們要代理的真實物件 Subject realSubject = new RealSubject(); // 我們要代理哪個真實物件,就將該物件傳進去,最後是通過該真實物件來呼叫其方法的 InvocationHandler handler = new DynamicProxy(realSubject); /* * 通過Proxy的newProxyInstance方法來建立我們的代理物件,我們來看看其三個引數 * 第一個引數 handler.getClass().getClassLoader() ,我們這裡使用handler這個類的ClassLoader物件來載入我們的代理物件 * 第二個引數realSubject.getClass().getInterfaces(),我們這裡為代理物件提供的介面是真實物件所實行的介面,表示我要代理的是該真實物件,這樣我就能呼叫這組介面中的方法了 * 第三個引數handler, 我們這裡將這個代理物件關聯到了上方的 InvocationHandler 這個物件上 */ Subject subject = (Subject)Proxy.newProxyInstance(handler.getClass().getClassLoader(), realSubject .getClass().getInterfaces(), handler); System.out.println(subject.getClass().getName()); subject.rent(); subject.hello("world"); } }
參考資料: