日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程语言 > asp.net >内容正文

asp.net

23种设计模式——JDK动态代理(AOP)

發(fā)布時(shí)間:2024/3/7 asp.net 40 豆豆
生活随笔 收集整理的這篇文章主要介紹了 23种设计模式——JDK动态代理(AOP) 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

文章目錄

  • 01 代理
    • 1.1 什么是代理?
    • 1.2 為什么要找中介
  • 02 靜態(tài)代理
    • 2.1 使用代理模式的作用
    • 2.2 實(shí)現(xiàn)代理的方式
    • 2.3 具體實(shí)現(xiàn)
    • 2.4 靜態(tài)代理的優(yōu)缺點(diǎn)
  • 03 動(dòng)態(tài)代理
    • 3.1 靜態(tài)代理和動(dòng)態(tài)代理模式的對(duì)比
    • 3.2 動(dòng)態(tài)代理的介紹
    • 3.3 回顧反射 Method類(lèi)
      • 3.3.1 class.getMethod
      • 3.3.2 Method.invoke
    • 3.4 JDK動(dòng)態(tài)代理
      • 3.4.1 Interface InvocationHandler
      • 3.4.2 Method
      • 3.4.3 Proxy類(lèi)
    • 3.5 JDK動(dòng)態(tài)代理實(shí)現(xiàn)步驟
    • 3.6 靜態(tài)代理的優(yōu)缺點(diǎn)
  • 04 實(shí)現(xiàn)動(dòng)態(tài)代理的步驟
  • 05 JDK動(dòng)態(tài)代理執(zhí)行流程
  • 06 靜態(tài)代理項(xiàng)目中的應(yīng)用
  • 07 完結(jié)

01 代理

1.1 什么是代理?

代理,在我們?nèi)粘I钪芯陀畜w現(xiàn),代購(gòu),中介,換ip,商家等等.

比如有一家美國(guó)的大學(xué),可以對(duì)全世界招生.留學(xué)中介(代理 )

留學(xué)中介(代理):幫助這家美國(guó)的學(xué)校招生,中介是學(xué)校的代理中介是代替學(xué)校完成招生功能

代理特點(diǎn)

  • 中介和代理他們要做的事情是一致的:招生
  • 中介是學(xué)校代理,學(xué)校是目標(biāo)
  • 家長(zhǎng)-------->中介(學(xué)校介紹,辦理入學(xué)手續(xù))---------->美國(guó)學(xué)校
  • 中介是代理,收取費(fèi)用
  • 1.2 為什么要找中介

    1.中介是專(zhuān)業(yè)的,方便.
    2.家長(zhǎng)現(xiàn)在不能自己去找學(xué)校。家長(zhǎng)沒(méi)有能力訪問(wèn)學(xué)校.或者美國(guó)學(xué)校不接收個(gè)人來(lái)訪

    買(mǎi)東西都是商家賣(mài), 商家是某個(gè)商品的代理, 你個(gè)人買(mǎi)東西,肯定不會(huì)讓你接觸到廠家的.

    02 靜態(tài)代理

    2.1 使用代理模式的作用

  • 功能增強(qiáng):在你原有的功能上,增加了額外的功能.新增加的功能,叫做功能增強(qiáng)
  • 控制訪問(wèn):代理類(lèi)不讓你訪問(wèn)目標(biāo),例如商家不讓用戶(hù)訪問(wèn)廠家
  • 2.2 實(shí)現(xiàn)代理的方式

    1)代理類(lèi)是自己手工實(shí)現(xiàn)的,自己創(chuàng)建一個(gè)java類(lèi),表示代理類(lèi)
    2)同時(shí)你所要代理的目標(biāo)

    特點(diǎn):
    1)實(shí)現(xiàn)簡(jiǎn)單
    2)容易理解

    模擬一個(gè)用戶(hù)購(gòu)買(mǎi)u盤(pán)的行為。
    用戶(hù):客戶(hù)端類(lèi)
    商家:代理,代理某個(gè)品牌的u盤(pán)。
    廠家:目標(biāo)類(lèi)。
    三者的關(guān)系:用戶(hù)(客戶(hù)端)-—-商家(代理)-—-廠家(目標(biāo))
    商家和廠家都是賣(mài)u盤(pán)的,他們完成的功能是一致的,都是賣(mài)u盤(pán)。

    實(shí)現(xiàn)步驟:

    實(shí)現(xiàn)步驟
    1.創(chuàng)建一個(gè)接口,定義賣(mài)u盤(pán)的方法,表示你的廠家和商家做的事情
    2.創(chuàng)建廠家類(lèi),實(shí)現(xiàn)1步驟的接口
    3.創(chuàng)建商家,就是代理,也需要實(shí)現(xiàn)1步驟中的接口
    4.創(chuàng)建客戶(hù)端類(lèi),調(diào)用商家的方法買(mǎi)一個(gè)u盤(pán)

    2.3 具體實(shí)現(xiàn)

    實(shí)現(xiàn)步驟
    1.創(chuàng)建一個(gè)接口,定義賣(mài)u盤(pán)的方法,表示你的廠家和商家做的事情

    package com.rango.service; public interface usbSell {/*** 定義一個(gè)方法 參數(shù) amount:表示一次購(gòu)買(mǎi)的數(shù)量,暫時(shí)不用* 返回值表示一個(gè)u盤(pán)的價(jià)格* @param amount* @return*/float sell(int amount); }

    2.創(chuàng)建廠家類(lèi),實(shí)現(xiàn)1步驟的接口

    package com.rango.factory;import com.rango.service.usbSell; //目標(biāo)類(lèi):金士頓廠家,不接受用戶(hù)的單獨(dú)購(gòu)買(mǎi) public class UsbKingFactory implements usbSell {/*** 定義一個(gè)方法 參數(shù) amount:表示一次購(gòu)買(mǎi)的數(shù)量,暫時(shí)不用* 返回值表示一個(gè)u盤(pán)的價(jià)格** @param amount* @return*/@Override //一個(gè)128G的U盤(pán)是85元. // 后期根據(jù)amount,可以實(shí)現(xiàn)不同的價(jià)格,例如10000個(gè),單擊是80,50000個(gè)75public float sell(int amount) {return 85.0f*amount;} }

    3.創(chuàng)建商家,就是代理,也需要實(shí)現(xiàn)1步驟中的接口

    package com.rango.business;import com.rango.factory.UsbKingFactory; import com.rango.service.usbSell;//淘寶是一個(gè)商家,代理金士頓U盤(pán)的銷(xiāo)售 public class TaoBao implements usbSell { // 聲明 商家代理的廠家具體是誰(shuí)private UsbKingFactory factory =new UsbKingFactory();@Override // 實(shí)現(xiàn)銷(xiāo)售U盤(pán)功能public float sell(int amount) { // 向廠家發(fā)送訂單,告訴廠家,我買(mǎi)了U盤(pán),廠家發(fā)貨 // 發(fā)送給工廠,我需要的訂單,返回報(bào)價(jià)float price = factory.sell(amount); // 商家需要加價(jià)也就是代理要增加價(jià)格price = price + 25; //在目標(biāo)類(lèi)的方法調(diào)用后,你做的其他功能,都是增強(qiáng)的意思System.out.println("淘寶再給你返回一個(gè)優(yōu)惠券,或者紅包"); // 增加的價(jià)格return price;} }

    4.創(chuàng)建客戶(hù)端類(lèi),調(diào)用商家的方法買(mǎi)一個(gè)u盤(pán)

    import com.rango.business.TaoBao;public class shopMain {public static void main(String[] args){ // 創(chuàng)建代理的商家淘寶對(duì)象TaoBao taoBao = new TaoBao(); // 我只向淘寶買(mǎi)一件產(chǎn)品,得到報(bào)價(jià)float price = taoBao.sell(2);System.out.println("購(gòu)買(mǎi)一件產(chǎn)品.淘寶的報(bào)價(jià)為: "+price);} }

    代理類(lèi)完成的功能:

  • 目標(biāo)類(lèi)中方法的調(diào)用
  • 功能增強(qiáng)
  • 所屬我們只有一個(gè)代理商,我們實(shí)際上可以寫(xiě)多個(gè)代理商,

    2.4 靜態(tài)代理的優(yōu)缺點(diǎn)

    優(yōu)點(diǎn):

  • 實(shí)現(xiàn)簡(jiǎn)單
  • 容易簡(jiǎn)單
  • 確定:當(dāng)你的項(xiàng)目中,目標(biāo)類(lèi)的代理類(lèi)很多的時(shí)候,有以下的缺點(diǎn)

  • 當(dāng)目標(biāo)類(lèi)增加了,代理類(lèi)可能也需要成倍的增加
  • 當(dāng)你的接口中功能在增加了,或者修改了,會(huì)影響眾多的實(shí)現(xiàn)類(lèi),廠家類(lèi),代理都需要修改,影響比較多.
  • 03 動(dòng)態(tài)代理

    1)什么是動(dòng)態(tài)代理?

    使用jdk的反射機(jī)制,創(chuàng)建對(duì)象的能力,創(chuàng)建的是代理類(lèi)的的對(duì)象.而不用我們創(chuàng)建類(lèi)文件,不用寫(xiě)java文件, 什么叫動(dòng)態(tài)?在程序執(zhí)行時(shí),調(diào)用jdk提供的方法才能創(chuàng)建代理類(lèi)的對(duì)象

    3.1 靜態(tài)代理和動(dòng)態(tài)代理模式的對(duì)比

    在靜態(tài)代理中目標(biāo)很多的時(shí)候,可以使用動(dòng)態(tài)代理,避免靜態(tài)代理的缺點(diǎn)

    在靜態(tài)代理中目標(biāo)類(lèi)很多時(shí)候,可以使用動(dòng)態(tài)代理,避免靜態(tài)代理的缺點(diǎn)。
    動(dòng)態(tài)代理中目標(biāo)類(lèi)即使很多,

  • 代理類(lèi)數(shù)量可以很少,
  • 當(dāng)你修改了接口中的方法時(shí),不會(huì)影響代理類(lèi)。
  • 動(dòng)態(tài)代理:在程序執(zhí)行過(guò)程中,使用jdk的反射機(jī)制,創(chuàng)建代理類(lèi)對(duì)象,并動(dòng)態(tài)的指定要代理目標(biāo)類(lèi)。

    換句話說(shuō):動(dòng)態(tài)代理是一種創(chuàng)建java象的能力,讓你不用創(chuàng)建 TaoBao類(lèi)就能創(chuàng)建代理類(lèi)對(duì)象,除去了中間商

    在java中,要想創(chuàng)建對(duì)象

  • 創(chuàng)建類(lèi)文件,java 文件編譯為class
  • 使用構(gòu)造方法,創(chuàng)建類(lèi)的對(duì)象
  • 3.2 動(dòng)態(tài)代理的介紹

  • 動(dòng)態(tài)代理是指代理類(lèi)對(duì)象在程序運(yùn)行時(shí)由JVM根據(jù)反射機(jī)制動(dòng)態(tài)生成的。動(dòng)態(tài)代理不需要定義代理類(lèi)的,java源文件。
  • 動(dòng)態(tài)代理其實(shí)就是jdk運(yùn)行期間,動(dòng)態(tài)創(chuàng)建class字節(jié)碼并加載到JVM。
  • 動(dòng)態(tài)代理的實(shí)現(xiàn)方式常用的有兩種:使用JDK代理,與通過(guò)CGLlB動(dòng)態(tài)代理。
  • 動(dòng)態(tài)代理的實(shí)現(xiàn):

  • jdk動(dòng)態(tài)代理(理解):使用java反射包中的類(lèi)和接口實(shí)現(xiàn)動(dòng)態(tài)代理的功能,反射包java.lang.reflect,里面有三個(gè)類(lèi):InvocationHandler,Method,Proxy
  • cglib動(dòng)態(tài)代理(了解): cglib是第三方的工具庫(kù),創(chuàng)建代理對(duì)象
  • cglib的原理是繼承,cglib通過(guò)繼承目標(biāo)類(lèi),創(chuàng)建它的子類(lèi),在子類(lèi)中
    重寫(xiě)父類(lèi)中同名的方法,實(shí)現(xiàn)功能的修改。
  • 因?yàn)閏glib是繼承,重寫(xiě)方法,所以要求目標(biāo)類(lèi)不能是fina1的,方法也不能是final的。cglib的要求目標(biāo)類(lèi)比較寬松,只要能繼承就可以了。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("張三"); // 以上是常規(guī)方法執(zhí)行sayhello // 下面我們使用反射機(jī)制進(jìn)行創(chuàng)建sayhello方法,核心Method(類(lèi)中的方法)HelloServiceImpl target = new HelloServiceImpl(); // 獲取sayhello名稱(chēng)對(duì)應(yīng)的Method類(lèi)對(duì)象 // public Method getM ethod(String name, Class<?>... parameterTypes) // 加入,該方法的參數(shù)有多個(gè)該怎么辦? // parameterTypes參數(shù)是一個(gè)類(lèi)對(duì)象數(shù)組,按聲明的順序標(biāo)識(shí)方法的形式參數(shù)類(lèi)型。Method method = HelloService.class.getMethod("sayhello", String.class); // 通過(guò)Metho可以執(zhí)行sayhello方法的調(diào)用/** public Object invoke(Object obj, Object... args)* 表示執(zhí)行方法的調(diào)用* 參數(shù):* 1.Object,表示對(duì)象,要執(zhí)行這個(gè)對(duì)象的方法* 2.Object...args,方法執(zhí)行時(shí)的參數(shù)值* 返回值:* Object:方法執(zhí)行后的返回值* */Object ret = method.invoke(target, "李四");} }

    3.3 回顧反射 Method類(lèi)

    Method類(lèi)的結(jié)構(gòu)圖

    • Class Method
      • java.lang.Object
        • java.lang.reflect.AccessibleObject
          • java.lang.reflect.Executable
            • java.lang.reflect.Method

    3.3.1 class.getMethod

    Method method = HelloService.class.getMethod("sayhello", String.class,Integer.class);

    提出問(wèn)題?

    public Method getMethod(String name, Class<?>... parameterTypes)

    加入該方法的參數(shù)有多個(gè)該怎么辦?
    parameterTypes參數(shù)是一個(gè)類(lèi)對(duì)象數(shù)組,按聲明的順序標(biāo)識(shí)方法的形式參數(shù)類(lèi)型。

    3.3.2 Method.invoke

    public Object invoke(Object obj,Object... args) * public Object invoke(Object obj, Object... args) * 表示執(zhí)行方法的調(diào)用 * 參數(shù): * 1.Object,表示對(duì)象,要執(zhí)行這個(gè)對(duì)象的方法 * 2.Object...args,方法執(zhí)行時(shí)的參數(shù)值 * 返回值: * Object:方法執(zhí)行后的返回值 *

    3.4 JDK動(dòng)態(tài)代理

    jdk動(dòng)態(tài)代理:
    1.反射, Method類(lèi),表示方法。類(lèi)中的方法。通過(guò)Method可以執(zhí)行某個(gè)方法

    2.jdk動(dòng)態(tài)代理的實(shí)現(xiàn)
    反射包java.lang. reflect,里面有三個(gè)類(lèi):InvocationHandler,Method,Proxy

    3.4.1 Interface InvocationHandler

    public interface InvocationHandler

    InvocationHandler是由代理實(shí)例的調(diào)用處理程序?qū)崿F(xiàn)的接口 。
    每個(gè)代理實(shí)例都有一個(gè)關(guān)聯(lián)的調(diào)用處理程序。 當(dāng)在代理實(shí)例上調(diào)用方法時(shí),方法調(diào)用將被編碼并分派到其調(diào)用處理程序的invoke方法。

    1)InvocationHandler接口(調(diào)用處理器):就一個(gè)方法 invoke()
    invoke():表示代理對(duì)象要執(zhí)行的功能代碼。你的代理類(lèi)要完成的功能就寫(xiě)在
    invoke()方法中。

    代理類(lèi)完成的功能1.調(diào)用目標(biāo)方法,執(zhí)行目標(biāo)方法的功能2.功能增強(qiáng),在目標(biāo)方法調(diào)用時(shí),增加功能

    方法原型:

    參數(shù):object proxy:jdk創(chuàng)建的代理對(duì)象,無(wú)需賦值。Method method:目標(biāo)類(lèi)中的方法,jdk提供method對(duì)象的object[]args:目標(biāo)類(lèi)中方法的參數(shù),jdk提供的。 Object invoke(Object proxy,方法 method,Object[] args)throws Throwable處理代理實(shí)例上的方法調(diào)用并返回結(jié)果。

    3.4.2 Method

    2)Method類(lèi):表示方法的,確切的說(shuō)就是目標(biāo)類(lèi)中的方法。
    作用:通過(guò) Method可以執(zhí)行某個(gè)目標(biāo)類(lèi)的方法, Method. invoke();
    method. invoke(目標(biāo)對(duì)象,方法的參數(shù))

    object ret= method. invoke(service22,"李四")

    說(shuō)明:method.invoke()就是為了用來(lái)執(zhí)行目標(biāo)方法的,等同于靜態(tài)代理中的

    // 向廠家發(fā)送訂單,告訴廠家,我買(mǎi)了U盤(pán),廠家發(fā)貨// 發(fā)送給工廠,我需要的訂單,返回報(bào)價(jià)float price = factory.sell(amount);

    3.4.3 Proxy類(lèi)

    3)proxy類(lèi):核心的對(duì)象,創(chuàng)建代理對(duì)象。之前創(chuàng)建對(duì)象都是new類(lèi)的構(gòu)造方法()
    現(xiàn)在我們是使用proxy類(lèi)的方法,代替new的使用。
    方法:靜態(tài)方法 newProxyInstance()
    作用是:創(chuàng)建代理對(duì)象,等同于靜態(tài)代理中的TaoBao taoBao=new TaoBao()

    我們來(lái)觀察方法原型

    public static Object newProxyInstance( ClassLoader loader,Class<?>[] interfaces,InvocationHandler h) throws IllegalArgumentException

    參數(shù):

  • ClassLoader loader 類(lèi)加載器,負(fù)責(zé)向內(nèi)存中加載對(duì)象的,使用反射機(jī)制獲取對(duì)象的classLoader,
  • 如何獲取? 類(lèi) a, a.getCalss().getClassLoader(),目標(biāo)對(duì)象的類(lèi)加載器

    這里我們細(xì)分:每一個(gè)類(lèi)都繼承Object類(lèi),在Object中有一個(gè)getClass方法,表示 類(lèi)對(duì)象的運(yùn)行時(shí)類(lèi)的Class對(duì)象。 而Class類(lèi)里面有一個(gè)public ClassLoader getClassLoader()方法

  • Class<?>[] interfaces: 接口,目標(biāo)對(duì)象實(shí)現(xiàn)的接口,也是反射獲取的
  • InvocationHandler h : 我們自己寫(xiě)的,代理類(lèi)要完成的功能
  • 返回值也就是代理對(duì)象

    3.5 JDK動(dòng)態(tài)代理實(shí)現(xiàn)步驟

    實(shí)現(xiàn)步驟
    1.創(chuàng)建一個(gè)接口,定義賣(mài)u盤(pán)的方法,表示你的廠家和商家做的事情

    package com.rango.service; public interface usbSell {/*** 定義一個(gè)方法 參數(shù) amount:表示一次購(gòu)買(mǎi)的數(shù)量,暫時(shí)不用* 返回值表示一個(gè)u盤(pán)的價(jià)格* @param amount* @return*/float sell(int amount); }

    2.創(chuàng)建廠家類(lèi),實(shí)現(xiàn)1步驟的接口

    package com.rango.factory;import com.rango.service.usbSell; //目標(biāo)類(lèi):金士頓廠家,不接受用戶(hù)的單獨(dú)購(gòu)買(mǎi) public class UsbKingFactory implements usbSell {/*** 定義一個(gè)方法 參數(shù) amount:表示一次購(gòu)買(mǎi)的數(shù)量,暫時(shí)不用* 返回值表示一個(gè)u盤(pán)的價(jià)格** @param amount* @return*/@Override //一個(gè)128G的U盤(pán)是85元. // 后期根據(jù)amount,可以實(shí)現(xiàn)不同的價(jià)格,例如10000個(gè),單擊是80,50000個(gè)75public float sell(int amount) {return 85.0f*amount;} }

    3.創(chuàng)建商家,就是代理,也需要實(shí)現(xiàn)1步驟中的接口

    package com.rango.business;import com.rango.factory.UsbKingFactory; import com.rango.service.usbSell;//淘寶是一個(gè)商家,代理金士頓U盤(pán)的銷(xiāo)售 public class TaoBao implements usbSell { // 聲明 商家代理的廠家具體是誰(shuí)private UsbKingFactory factory =new UsbKingFactory();@Override // 實(shí)現(xiàn)銷(xiāo)售U盤(pán)功能public float sell(int amount) { // 向廠家發(fā)送訂單,告訴廠家,我買(mǎi)了U盤(pán),廠家發(fā)貨 // 發(fā)送給工廠,我需要的訂單,返回報(bào)價(jià)float price = factory.sell(amount); // 商家需要加價(jià)也就是代理要增加價(jià)格price = price + 25; //在目標(biāo)類(lèi)的方法調(diào)用后,你做的其他功能,都是增強(qiáng)的意思System.out.println("淘寶再給你返回一個(gè)優(yōu)惠券,或者紅包"); // 增加的價(jià)格return price;} }

    4.創(chuàng)建客戶(hù)端類(lèi),調(diào)用商家的方法買(mǎi)一個(gè)u盤(pán)

    import com.rango.business.TaoBao;public class shopMain {public static void main(String[] args){ // 創(chuàng)建代理的商家淘寶對(duì)象TaoBao taoBao = new TaoBao(); // 我只向淘寶買(mǎi)一件產(chǎn)品,得到報(bào)價(jià)float price = taoBao.sell(2);System.out.println("購(gòu)買(mǎi)一件產(chǎn)品.淘寶的報(bào)價(jià)為: "+price);} }

    所以我們?cè)俅慰偨Y(jié)代理類(lèi)完成的功能:

  • 目標(biāo)類(lèi)中方法的調(diào)用
  • 功能增強(qiáng)
  • 所屬我們只有一個(gè)代理商,我們實(shí)際上可以寫(xiě)多個(gè)代理商,

    3.6 靜態(tài)代理的優(yōu)缺點(diǎn)

    我們?cè)俅慰偨Y(jié)一下靜態(tài)代理的優(yōu)缺點(diǎn)

    優(yōu)點(diǎn):

  • 實(shí)現(xiàn)簡(jiǎn)單
  • 容易簡(jiǎn)單
  • 確定:當(dāng)你的項(xiàng)目中,目標(biāo)類(lèi)的代理類(lèi)很多的時(shí)候,有一下的缺點(diǎn)

  • 當(dāng)目標(biāo)類(lèi)增加了,代理類(lèi)可能也需要成倍的增加
  • 當(dāng)你的接口中功能在增加了,或者修改了,會(huì)影響眾多的實(shí)現(xiàn)類(lèi),廠家類(lèi),代理都需要修改,影響比較多.
  • 所以我們繼續(xù)學(xué)習(xí)動(dòng)態(tài)代理

    04 實(shí)現(xiàn)動(dòng)態(tài)代理的步驟

  • 創(chuàng)建接口,定義目標(biāo)類(lèi)要完成的功能
  • 創(chuàng)建目標(biāo)類(lèi)實(shí)現(xiàn)接口
  • 創(chuàng)建InvocationHandler接口的實(shí)現(xiàn)類(lèi),在invoke方法中完成代理類(lèi)的功能
  • 調(diào)用目標(biāo)方法
  • 增強(qiáng)功能
  • 使用Proxy類(lèi)的靜態(tài)方法,創(chuàng)建代理對(duì)象,并把返回值轉(zhuǎn)換成接口類(lèi)型
  • 第一步:創(chuàng)建接口,定義目標(biāo)所需功能

    public interface UsbSell {float sell(int amount); }

    第二步:創(chuàng)建目標(biāo)類(lèi)實(shí)現(xiàn)接口

    public class UsbKingFactory implements UsbSell {@Overridepublic float sell(int amount) {System.out.println("目標(biāo)類(lèi)中,執(zhí)行了sell目標(biāo)方法");return 85.02f;} }

    我們寫(xiě)了接口類(lèi),定義了功能,寫(xiě)了代理類(lèi),實(shí)現(xiàn)了接口功能,按照以前的操作,現(xiàn)在就需要寫(xiě)一個(gè)真正的代理類(lèi),創(chuàng)建對(duì)象.

    第三步: 創(chuàng)建Invocationhandler實(shí)現(xiàn)類(lèi).在invoke()方法中完成代理類(lèi)的對(duì)象

    1.調(diào)用目標(biāo)的方法

    2.增強(qiáng)功能

    public class MyHandle implements InvocationHandler {@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {return null;} }

    我們就在以前代理類(lèi)的實(shí)現(xiàn)方法上進(jìn)行修改

    //之前的代理類(lèi)public class TaoBao implements usbSell {// 聲明 商家代理的廠家具體是誰(shuí)private UsbKingFactory factory =new UsbKingFactory();@Override// 實(shí)現(xiàn)銷(xiāo)售U盤(pán)功能public float sell(int amount) {// 向廠家發(fā)送訂單,告訴廠家,我買(mǎi)了U盤(pán),廠家發(fā)貨// 發(fā)送給工廠,我需要的訂單,返回報(bào)價(jià)float price = factory.sell(amount);// 商家需要加價(jià)也就是代理要增加價(jià)格price = price + 25;//在目標(biāo)類(lèi)的方法調(diào)用后,你做的其他功能,都是增強(qiáng)的意思System.out.println("淘寶再給你返回一個(gè)優(yōu)惠券,或者紅包");// 增加的價(jià)格return price;}}

    調(diào)用目標(biāo)的方法

    //傳入是誰(shuí)的對(duì)象,就給誰(shuí)創(chuàng)建代理public MyHandle(Object target) {this.target = target;} invoke里面的設(shè)置Object res =null;// 向廠家發(fā)送訂單,告訴廠家,我買(mǎi)了U盤(pán),廠家發(fā)貨// 發(fā)送給工廠,我需要的訂單,返回報(bào)價(jià) // float price = factory.sell(amount);res = method.invoke(target,args); //待執(zhí)行目標(biāo)方法,執(zhí)行后返回值

    第四步: 使用Proxy類(lèi)的靜態(tài)方法,創(chuàng)建代理對(duì)象,并把返回值轉(zhuǎn)換成接口類(lèi)型

    創(chuàng)建一個(gè)MainShop類(lèi).

    public class MainShop {public static void main(String[] args){ // 1.創(chuàng)建對(duì)象,使用Proxy // 2.創(chuàng)建目標(biāo)對(duì)象UsbSell factory = new UsbKingFactory(); // 3.創(chuàng)建Invocationhandler對(duì)象InvocationHandler myHandle = new MyHandle(factory);// 4.創(chuàng)建代理對(duì)象UsbSell proxy = (UsbSell) Proxy.newProxyInstance(factory.getClass().getClassLoader(),factory.getClass().getInterfaces(),myHandle); // 通過(guò)代理執(zhí)行方法float price = proxy.sell(1);System.out.println("通過(guò)動(dòng)態(tài)代理對(duì)象,調(diào)用方法:" +price);} }

    執(zhí)行成功.和之前動(dòng)態(tài)代理模式一樣

    05 JDK動(dòng)態(tài)代理執(zhí)行流程

    Proxy類(lèi),實(shí)現(xiàn)動(dòng)態(tài)代理的流程,使用返回指定接口的代理類(lèi)實(shí)例,

    我們此時(shí)debug一下程序,在invok實(shí)現(xiàn)類(lèi)中打一個(gè)斷點(diǎn)
    此時(shí)我們?cè)儆^察,代理對(duì)象MyHandler里面的invoke方法的參數(shù)

    06 靜態(tài)代理項(xiàng)目中的應(yīng)用

    我們需要知道代理能做什么?

    在不改變?cè)瓉?lái)目標(biāo)方法功能的前提下,可以在代理中增強(qiáng)自己的功能代碼,程序開(kāi)發(fā)中的意思,

    比如:你所在的項(xiàng)目,有一個(gè)功能是其他人(公司其他部門(mén),其他小組的人)寫(xiě)好的,你可以使用

    //比如,同事開(kāi)發(fā)一個(gè)GoNong類(lèi) GoNong.class , GoNong gn=new GoNong()//我們需要增加一個(gè)print方法

    我們發(fā)現(xiàn)這個(gè)功能現(xiàn)在還存在缺點(diǎn),不能完全滿足我項(xiàng)目的需要,我需要在print()執(zhí)行過(guò)后,需要自己再增加代理,使用什么方法那,肯定是代理,因?yàn)閯e人不會(huì)讓我們看源文件

    執(zhí)行步驟:

  • 我們先建立一個(gè)接口功能,很簡(jiǎn)單的一個(gè)功能
  • public interface HelloService {/*** 打印報(bào)表,報(bào)表* @param name* @return*/int print (String name); }
  • 我們?cè)偌觽€(gè)接口實(shí)現(xiàn)類(lèi)
  • public class GoNeng implements HelloService {@Overridepublic int print(String name) {System.out.println("其他人寫(xiě)好的這個(gè)方法!");return 2;} }
  • 我們?nèi)绻鄬?duì)上述功能進(jìn)行修改,我們不可能直接去在原方法上進(jìn)行修改
  • 我們?cè)O(shè)置一個(gè)類(lèi)來(lái)使用這個(gè)接口

    public class MyApp {public static void main(String[] args){GoNeng gn = new GoNeng();int i = gn.print("nihao1");System.out.println("num" +i);} }

    問(wèn)題是如果我們想修改這個(gè)功能改怎么辦?在不修改源代碼的基礎(chǔ)上,我們可以創(chuàng)建一個(gè)代理類(lèi),來(lái)增強(qiáng)這個(gè)類(lèi)方法,

  • 設(shè)置一個(gè)代理類(lèi)實(shí)現(xiàn)功能的增強(qiáng)和代理
  • public class MyInvocationHandler implements InvocationHandler {private Object target=null;public MyInvocationHandler(Object target) {this.target = target;}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable { // 調(diào)用目標(biāo)方法,執(zhí)行print()得到2Object res = method.invoke(target,args); //返回為2的結(jié)果//我們可以把結(jié)果再乘以2if (res!=null){Integer num = (Integer) res;res = num*2; }return null;} }
  • 我們?nèi)曰氐街鞣椒ɡ锩孢M(jìn)行測(cè)試
  • public class MyApp {public static void main(String[] args){ // GoNeng gn = new GoNeng(); // int i = gn.print("nihao1"); // System.out.println("num" +i);GoNeng goNeng = new GoNeng();InvocationHandler handler = new MyInvocationHandler(goNeng);HelloService proxy = (HelloService) Proxy.newProxyInstance(goNeng.getClass().getClassLoader(), goNeng.getClass().getInterfaces(),handler);int num = proxy.print("市場(chǎng)");System.out.println("我們期望得到的 num =="+num);} }

    測(cè)試System.out.println("動(dòng)態(tài)代理類(lèi)參數(shù)接口"+goNeng.getClass().getInterfaces()[0].getName());

    動(dòng)態(tài)代理類(lèi)參數(shù)接口com.rango.service.HelloService 其他人寫(xiě)好的這個(gè)方法! 我們期望得到的 num ==4

    07 完結(jié)

    動(dòng)態(tài)代理,必須要有接口出現(xiàn),如果沒(méi)有,我們可以使用cglib實(shí)現(xiàn)

    總結(jié)

    以上是生活随笔為你收集整理的23种设计模式——JDK动态代理(AOP)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

    如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。