Java-JDK動態代理(AOP)使用及實現原理分析
Java-JDK動態代理(AOP)使用及實現原理分析
第一章:代理的介紹
介紹:我們需要掌握的程度
動態代理(理解) 基於反射機制
掌握的程度:
1.什麼是動態代理?
2.動態代理能夠做什麼?
後面我們在用Spirng和Mybatis的時候,要理解怎麼使用的.
1.什麼是代理?
代理,在我們日常生活之中就有體現,代購,中介,換ip,商家等等.
比如有一家美國的大學,可以對全世界招生.留學中介(代理 )
留學中介(代理):幫助這家美國的學校招生,中介是學校的代理中介是代替學校完成招生功能
代理特點
- 中介和代理他們要做的事情是一致的:招生
- 中介是學校代理,學校是目標
- 家長——–>中介(學校介紹,辦理入學手續)———->美國學校
- 中介是代理,收取費用
2.為什麼要找中介
為什麼要找中介?
1.中介是專業的,方便.
2.家長現在不能自己去找學校。家長沒有能力訪問學校.或者美國學校不接收個人來訪
買東西都是商家賣, 商家是某個商品的代理, 你個人買東西,肯定不會讓你接觸到廠家的.
第二章:靜態代理
2.1 使用代理模式的作用
- 功能增強:在你原有的功能上,增加了額外的功能.新增加的功能,叫做功能增強
- 控制訪問:代理類不讓你訪問目標,例如商家不讓用戶訪問廠家
2.2 實現代理的方式
1.靜態代理:
1)代理類是自己手工實現的,自己創建一個java類,表示代理類
2)同時你所要代理的目標
特點:1)實現簡單2)容易理解。
模擬一個用戶購買u盤的行為。
用戶是客戶端類
商家:代理,代理某個品牌的u盤。
廠家:目標類。
三者的關係:用戶(客戶端)-—-商家(代理)-—-廠家(目標)
商家和廠家都是賣u盤的,他們完成的功能是一致的,都是賣u盤。
實現步驟:
實現步驟
1.創建一個介面,定義賣u盤的方法,表示你的廠家和商家做的事情
2.創建廠家類,實現1步驟的介面
3.創建商家,就是代理,也需要實現1步驟中的介面
4.創建客戶端類,調用商家的方法買一個u盤
2.3 具體實現
實現步驟
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);
}
}
所以我們再次總結代理類完成的功能:
- 目標類中方法的調用
- 功能增強
所屬我們只有一個代理商,我們實際上可以寫多個代理商,
2.4 靜態代理的優缺點
我們再次總結一下靜態代理的優缺點
優點:
- 實現簡單
- 容易簡單
確定:當你的項目中,目標類的代理類很多的時候,有一下的缺點
- 當目標類增加了,代理類可能也需要成倍的增加
- 當你的介面中功能在增加了,或者修改了,會影響眾多的實現類,廠家類,代理都需要修改,影響比較多.
所以我們繼續學習動態代理
第三章 動態代理
本章,我們所掌握的是
1)什麼是動態代理?
使用jdk的反射機制,創建對象的能力,創建的是代理類的的對象.而不用我們創建類文件,不用寫java文件, 什麼叫動態?在程式執行時,調用jdk提供的方法才能創建代理類的對象
2)知道動態代理能做什麼?
2.1 靜態代理和動態代理模式的對比
在靜態代理中目標很多的時候,可以使用動態代理,避免靜態代理的缺點
在靜態代理中目標類很多時候,可以使用動態代理,避免靜態代理的缺點。
動態代理中目標類即使很多,
-
代理類數量可以很少,
-
當你修改了介面中的方法時,不會影響代理類。
動態代理:在程式執行過程中,使用jdk的反射機制,創建代理類對象,並動態的指定要代理目標類。
換句話說:動態代理是一種創建java象的能力,讓你不用創建 TaoBao類就能創建代理類對象,除去了中間商
在java中,要想創建對象
- 創建類文件,java 文件編譯為class
- 使用構造方法,創建類的對象
2.1 動態代理的介紹
- 動態代理是指代理類對象在程式運行時由JVM根據反射機制動態生成的。動態代理不需要定義代理類的,java源文件。
- 動態代理其實就是jdk運行期間,動態創建class位元組碼並載入到JVM。
- 動態代理的實現方式常用的有兩種:使用JDK代理,與通過CGLlB動態代理。
動態代理的實現:
- 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, "李四");
}
}
2.2 回顧反射 Method類
Method類的結構圖
- Class Method
- java.lang.Object
- java.lang.reflect.AccessibleObject
- java.lang.reflect.Executable
- java.lang.reflect.Method
2.2.1 class.getMethod
Method method = HelloService.class.getMethod("sayhello", String.class,Integer.class);
提出問題?
public Method getMethod(String name, Class<?>... parameterTypes)
加入,該方法的參數有多個該怎麼辦?
parameterTypes參數是一個類對象數組,按聲明的順序標識方法的形式參數類型。
2.2.2 Method.invoke
public Object invoke(Object obj,Object... args)
* public Object invoke(Object obj, Object... args)
* 表示執行方法的調用
* 參數:
* 1.Object,表示對象,要執行這個對象的方法
* 2.Object...args,方法執行時的參數值
* 返回值:
* Object:方法執行後的返回值
*