介紹:咱們須要掌握的程度java
動態代理(理解) 基於反射機制spring
掌握的程度:數組
1.什麼是動態代理?mybatis
2.動態代理可以作什麼?框架
後面咱們在用Spirng和Mybatis的時候,要理解怎麼使用的.ide
代理,在咱們平常生活之中就有體現,代購,中介,換ip,商家等等.工具
好比有一家美國的大學,能夠對全世界招生.留學中介(代理 )學習
留學中介(代理):幫助這家美國的學校招生,中介是學校的代理中介是代替學校完成招生功能
代理特色代理
爲何要找中介?
1.中介是專業的,方便.
2.家長如今不能本身去找學校。家長沒有能力訪問學校.或者美國學校不接收我的來訪code
買東西都是商家賣, 商家是某個商品的代理, 你我的買東西,確定不會讓你接觸到廠家的.
1.靜態代理:
1)代理類是本身手工實現的,本身建立一個java類,表示代理類
2)同時你所要代理的目標
特色:1)實現簡單2)容易理解。
模擬一個用戶購買u盤的行爲。
用戶是客戶端類
商家:代理,代理某個品牌的u盤。
廠家:目標類。
三者的關係:用戶(客戶端)-—-商家(代理)-—-廠家(目標)
商家和廠家都是賣u盤的,他們完成的功能是一致的,都是賣u盤。
實現步驟:
實現步驟
1.建立一個接口,定義賣u盤的方法,表示你的廠家和商家作的事情
2.建立廠家類,實現1步驟的接口
3.建立商家,就是代理,也須要實現1步驟中的接口
4.建立客戶端類,調用商家的方法買一個u盤
實現步驟
1.建立一個接口,定義賣u盤的方法,表示你的廠家和商家作的事情
package com.rango.service; public interface usbSell { /** * 定義一個方法 參數 amount:表示一次購買的數量,暫時不用 * 返回值表示一個u盤的價格 * @param amount * @return */ float sell(int amount); }
2.建立廠家類,實現1步驟的接口
package com.rango.factory; import com.rango.service.usbSell; //目標類:金士頓廠家,不接受用戶的單獨購買 public class UsbKingFactory implements usbSell { /** * 定義一個方法 參數 amount:表示一次購買的數量,暫時不用 * 返回值表示一個u盤的價格 * * @param amount * @return */ @Override //一個128G的U盤是85元. // 後期根據amount,能夠實現不一樣的價格,例如10000個,單擊是80,50000個75 public float sell(int amount) { return 85.0f*amount; } }
3.建立商家,就是代理,也須要實現1步驟中的接口
package com.rango.business; import com.rango.factory.UsbKingFactory; import com.rango.service.usbSell; //淘寶是一個商家,代理金士頓U盤的銷售 public class TaoBao implements usbSell { // 聲明 商家代理的廠家具體是誰 private UsbKingFactory factory =new UsbKingFactory(); @Override // 實現銷售U盤功能 public float sell(int amount) { // 向廠家發送訂單,告訴廠家,我買了U盤,廠家發貨 // 發送給工廠,我須要的訂單,返回報價 float price = factory.sell(amount); // 商家須要加價也就是代理要增長價格 price = price + 25; //在目標類的方法調用後,你作的其餘功能,都是加強的意思 System.out.println("淘寶再給你返回一個優惠券,或者紅包"); // 增長的價格 return price; } }
4.建立客戶端類,調用商家的方法買一個u盤
import com.rango.business.TaoBao; public class shopMain { public static void main(String[] args){ // 建立代理的商家淘寶對象 TaoBao taoBao = new TaoBao(); // 我只向淘寶買一件產品,獲得報價 float price = taoBao.sell(2); System.out.println("購買一件產品.淘寶的報價爲: "+price); } }
因此咱們再次總結代理類完成的功能:
- 目標類中方法的調用
- 功能加強
所屬咱們只有一個代理商,咱們實際上能夠寫多個代理商,
咱們再次總結一下靜態代理的優缺點
優勢:
肯定:當你的項目中,目標類的代理類不少的時候,有一下的缺點
因此咱們繼續學習動態代理
本章,咱們所掌握的是
1)什麼是動態代理?
使用jdk的反射機制,建立對象的能力,建立的是代理類的的對象.而不用咱們建立類文件,不用寫java文件, 什麼叫動態?在程序執行時,調用jdk提供的方法才能建立代理類的對象
2)知道動態代理能作什麼?
在靜態代理中目標不少的時候,能夠使用動態代理,避免靜態代理的缺點
在靜態代理中目標類不少時候,能夠使用動態代理,避免靜態代理的缺點。
動態代理中目標類即便不少,
代理類數量能夠不多,
當你修改了接口中的方法時,不會影響代理類。
動態代理:在程序執行過程當中,使用jdk的反射機制,建立代理類對象,並動態的指定要代理目標類。
換句話說:動態代理是一種建立java象的能力,讓你不用建立 TaoBao類就能建立代理類對象,除去了中間商
在java中,要想建立對象
動態代理的實現:
- jdk動態代理(理解):使用java反射包中的類和接口實現動態代理的功能,反射包java.lang.reflect,裏面有三個類:InvocationHandler,Method,Proxy
- cglib動態代理(瞭解): cglib是第三方的工具庫,建立代理對象
- cglib的原理是繼承,cglib經過繼承目標類,建立它的子類,在子類中
重寫父類中同名的方法,實現功能的修改。- 由於cglib是繼承,重寫方法,因此要求目標類不能是fina1的,方法也不能是final的。cglib的要求目標類比較寬鬆,只要能繼承就能夠了。cglib在不少的框架中使用,
好比mybatis,spring框架中都有使用。
package Test; import com.rango.Impl.HelloServiceImpl; import com.rango.service.HelloService; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; public class TestApp { public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { // HelloService service = new HelloServiceImpl(); // service.sayhello("張三"); // 以上是常規方法執行sayhello // 下面咱們使用反射機制進行建立sayhello方法,核心Method(類中的方法) HelloServiceImpl target = new HelloServiceImpl(); // 獲取sayhello名稱對應的Method類對象 // public Method getM ethod(String name, Class<?>... parameterTypes) // 加入,該方法的參數有多個該怎麼辦? // parameterTypes參數是一個類對象數組,按聲明的順序標識方法的形式參數類型。 Method method = HelloService.class.getMethod("sayhello", String.class); // 經過Metho能夠執行sayhello方法的調用 /* * public Object invoke(Object obj, Object... args) * 表示執行方法的調用 * 參數: * 1.Object,表示對象,要執行這個對象的方法 * 2.Object...args,方法執行時的參數值 * 返回值: * Object:方法執行後的返回值 * */ Object ret = method.invoke(target, "李四"); } }
Method類的結構圖
- Class Method
- java.lang.Object
- java.lang.reflect.AccessibleObject
- java.lang.reflect.Executable
- java.lang.reflect.Method
Method method = HelloService.class.getMethod("sayhello", String.class,Integer.class);
提出問題?
public Method getMethod(String name, Class<?>... parameterTypes)
加入,該方法的參數有多個該怎麼辦?
parameterTypes參數是一個類對象數組,按聲明的順序標識方法的形式參數類型。
public Object invoke(Object obj,Object... args)
* public Object invoke(Object obj, Object... args) * 表示執行方法的調用 * 參數: * 1.Object,表示對象,要執行這個對象的方法 * 2.Object...args,方法執行時的參數值 * 返回值: * Object:方法執行後的返回值 *