說明:圖片是我其它地方博客裏的java
package dproxy; /** *抽象主題 **/ interface Subject { void subjectMethod(int a,int b); } /** *具體主題 **/ /** *實現了Subject接口,而且覆蓋了subjectMethod方法 **/ package dproxy; public class RealSubject implements Subject { //Joinpoint鏈接點 @Override public void subjectMethod(int a, int b) { // TODO Auto-generated method stub System.out.println(a+"+"+b +"="+(a+b)); } } /** *代理處理 **/ package dproxy; import java.lang.reflect.InvocationHandler; //Aspect(方面)??? public class ProxyHandler implements InvocationHandler { private Object subject; public ProxyHandler(Object subject) { // TODO Auto-generated constructor stub this.subject = subject; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { before(); // TODO Auto-generated method stub System.out.println("調用真實主題的方法"); /** *用反射機制調用了realMethod方法 **/ method.invoke(subject, args); after(); return null; } //Advice(通知) public void before() { System.out.println("代理前的處理操做"); } //Advice(通知) public void after() { System.out.println("代理後的處理操做"); } }
invoke方法參數說明: invoke
方法的第一個參數是 proxy
是 Proxy.newProxyInstance
建立的對象,我在網上看到不少文章說這個參數是被代理類的對象即RealSubject的對象,這種說法是錯誤的,你們能夠用RTTI
對proxy
進行了解,它確實是 Proxy.newProxyInstance
建立的對象
構造器說明: ProxyHandler()
構造器接受一個參數,這個參數是被代理類即RealSubject
的對象。
invoke內部解析: 咱們在 invoke
函數裏面 經過 method.invoke(subject, args);
調用了真實主題,即被代理對象的某一個方法,注意 invoke
的第二個參數是 method
它指明調用被代理對象的哪個方法,第三個參數是該方法的參數。spring
package dproxy; import java.lang.reflect.Method; import java.lang.reflect.Proxy; public class Client { public static void main(String[] args) { // TODO Auto-generated method stub /** *建立真實主題 **/ Subject realSubject = new RealSubject(); /** *建立代理處理器 **/ ProxyHandler handler = new ProxyHandler(realSubject); /** *建立代理對象 **/ Subject proxy = (Subject) Proxy.newProxyInstance(realSubject.getClass() .getClassLoader(), realSubject.getClass().getInterfaces(), handler); /** *調用動態建立的代理對象的動態生成的subjectMethod方法 **/ proxy.subjectMethod(3, 5); //執行了3+5操做 並在該操做先後調用了附加方法 } }
說明1:Proxy.newProxyInstance建立了一個代理對象,而且以Subject的身份去調用一個貌似和Subject類如出一轍的接口subjectMethod因爲 proxy對象是Subject類型的 即 Subject proxy ,因此咱們執行 proxy.subjectMethod(3, 5);時感受不到在用代理。
說明2:咱們建立proxy時傳入了一個handler對象。在這個對象裏咱們調用了被代理的那個對象的方法,而且在其先後附加了方法。ide
執行流程:函數
1 在Client
建立了一個被代理的對象 realSubject
2 建立了一個代理處理器,這裏是代理處理器,並非代理類,由於它不是Subject
類型,也沒有和Subject
內部長的同樣的函數因此它不是代理對象,可是它對真實對象,即realSubject
對象的調用時由這個對象代替代理類來作的。也就是代理類將對被代理對象的調用的職責委託給了這個代理處理器
3 Proxy
類建立了一個對象,而後這個類經過 java
反射機制 將建立的這個對象變的類型變成了Subject
,建立的這個對象內部有一個代理處理器對象handler
4 由3建立的那個代理對象,執行proxy.subjectMethod(3, 5);
以Subject
的身份調用了一個和Subject
接口中的某個函數長的同樣的一個函數,這是由於proxy
是Subject
類型的一個對象
5 proxy
在subjectMethod
函數內部將對被代理對象的調用委託給了代理處理器對象handler
this
和spring AOP
的關係AOP
中的 Advice通知
就是咱們在被代理方法執行先後附加的方法AOP
中的 Joinpoint鏈接點
就是咱們須要執行的那個 3+5的方法AOP
中的 Aspect方面
若是咱們將全部的 Advice通知 提取出來放在 一個類中就構成 了 Aspect
方面 AOP
中的 Pointcut切入點
是全部符合相同規則的鏈接點的集合,例如全部以do開頭的方法,切入點內包含一套規則用來講明該切入點包含哪些連接點AOP
中的Introduction(引介)
引介是一種特殊的通知在不修改類代碼的前提下, Introduction
能夠在運行期爲類動態地添加一些方法或Field
AOP
中的Target(目標對象)
代理的目標對象(要加強的類) AOP
中的織入 Weaving
把切面應用到目標對象並建立新的代理對象的過程。切面在指定的鏈接點被織入到目標對象中。織入能夠在對象生命週期的編譯期、類加載期、運行期完成。Spring AOP
由於採用動態代理,因此是在 運行期 完成織入。AOP
中的Proxy(代理)
一個類被AOP織入加強後,就產生一個結果代理類spa