Spring AOP使用的其中一個底層技術就是Java的動態代理技術。Java的動態代理技術主要圍繞兩個類進行的 java
java.lang.reflect.InvocationHandler
java.lang.reflect.Proxy
首先從代碼層面說明Java動態代理是如何實現的,數組
業務邏輯接口:ide
/** * 建立一我的的接口,其中有一個吃的方法 */ public interface Person { public void eat(); }
建立一個實現該業務接口的類:測試
/** * 人接口的實現,實現吃飯的方法 */ public class PersonImpl implements Person { @Override public void eat() { System.out.println("吃主食、吃菜、喝湯..."); } }
此時,若是正常狀況若是想要調用Person這個接口,直接new它的實現類而後調用eat方法便可,可是若是想要實現一個Person的代理,而且在eat方法先後進行一些工做就須要使用Proxy和InvovationHandler;ui
InvocationHandler接口的實現類,(代理類中額外邏輯的實現就須要在這裏進行)this
/** * 代理類的額外邏輯實現類 */ public class InvocationHandlerImpl implements InvocationHandler { Person person; public InvocationHandlerImpl(Person person) { this.person = person; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { if(method.getName().equalsIgnoreCase("eat")) { System.out.println("洗手..."); method.invoke(person, args); System.out.println("刷牙"); } return person; } }
接下來就是使用Proxy生成代理類,Proxy須要業務邏輯接口,代理類額外實現邏輯InvocationHandler實現類idea
/** * 代理類產生而且測試 */ public class ProxyGenerate { @Test public void proxyTest() { Person person = new PersonImpl(); InvocationHandler invocationHandler = new InvocationHandlerImpl(person); Person personProxy = (Person)Proxy.newProxyInstance(Person.class.getClassLoader(), new Class[]{Person.class}, invocationHandler); personProxy.eat(); } }
輸出內容以下:代理
代理類已經成功的完成代理。code
AOP的功能就是在一個方法前、後、異常拋出等地方添加邏輯,與上面的過程是同樣的,因此這個技術就被用來實現Spring AOP的一個技術,可是這個只針對接口實現,若是想要給一個類添加AOP的邏輯,這個Proxy動態代理的技術暫時沒法適用,Spring AOP適用了CGLIB,支持類的動態代理,可是不屬於這一次的討論範疇。對象
知道怎麼用了以後是否是對Proxy這個感受很神奇,想知道是如何實現的呢,能夠深刻了解一下newProxyInstance這個方法:
找到上述內容,能夠看到這個是動態生成代理類字節數組的方法,因此咱們能夠經過這個方法瞭解到動態生成的代理類的結構:
/** * 代理類產生而且測試 */ public class ProxyGenerate { @Test public void proxyWatch() { byte[] classByte = ProxyGenerator.generateProxyClass("PersonDynamicProxy", new Class[]{Person.class}); try { FileOutputStream var1 = new FileOutputStream("PersonDynamicProxy" + ".class"); var1.write(classByte); var1.close(); } catch (IOException var2) { throw new InternalError("I/O exception saving generated file: " + var2); } } }
執行上述代碼會生成動態代理對象的.class文件
反編譯(jd-gui,idea)以後就能夠看到動態代理類的結構:
// // Source code recreated from a .class file by IntelliJ IDEA // (powered by Fernflower decompiler) // import com.smart.beanfactory.Person; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.lang.reflect.UndeclaredThrowableException; public final class PersonDynamicProxy extends Proxy implements Person { private static Method m1; private static Method m3; private static Method m0; private static Method m2; public PersonDynamicProxy(InvocationHandler var1) throws { super(var1); } public final boolean equals(Object var1) throws { try { return ((Boolean)super.h.invoke(this, m1, new Object[]{var1})).booleanValue(); } catch (RuntimeException | Error var3) { throw var3; } catch (Throwable var4) { throw new UndeclaredThrowableException(var4); } } public final void eat() throws { try { super.h.invoke(this, m3, (Object[])null); } catch (RuntimeException | Error var2) { throw var2; } catch (Throwable var3) { throw new UndeclaredThrowableException(var3); } } public final int hashCode() throws { try { return ((Integer)super.h.invoke(this, m0, (Object[])null)).intValue(); } catch (RuntimeException | Error var2) { throw var2; } catch (Throwable var3) { throw new UndeclaredThrowableException(var3); } } public final String toString() throws { try { return (String)super.h.invoke(this, m2, (Object[])null); } catch (RuntimeException | Error var2) { throw var2; } catch (Throwable var3) { throw new UndeclaredThrowableException(var3); } } static { try { m1 = Class.forName("java.lang.Object").getMethod("equals", new Class[]{Class.forName("java.lang.Object")}); m3 = Class.forName("com.smart.beanfactory.Person").getMethod("eat", new Class[0]); m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]); m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]); } catch (NoSuchMethodException var2) { throw new NoSuchMethodError(var2.getMessage()); } catch (ClassNotFoundException var3) { throw new NoClassDefFoundError(var3.getMessage()); } } }
能夠看出來,動態代理類首先經過反射的技術,將源接口中的方法均設置爲其靜態屬性(Method),而後針對每一個方法進行重寫。
重寫的邏輯是使用invocationHandler接口的invoke方法實現,每一個invoke方法在綁定相應的反射出來的靜態屬性便可。
舉例,好比上面Person接口的eat被反射未m3的靜態屬性中,重寫eat()方法是調用方法爲invoke(this, m3, args),其中invoke中會有額外添加的一些邏輯,