代理模式——Java

代理模式

在Java中代理模式是一種設計模式,是通過代理類來代替原始的對象,可以在不改變原始對象的基礎上,對它進行擴展(新增一些新功能)。在目標方法的執行的執行前后添加一些自定義的方法。

靜態代理

步驟:
1.創建一個接口以及它的實現類
2.創建它的代理類實現該接口(重寫接口中的方法,自定義一些新功能)
3.在代理類中注入目標類,并且調用代理類中的相關方法。
具體實現如下:
(1.)接口和其實現類

public interface SsSercive {void say(String message);
}

實現類

public class ImpService implements SsSercive {public void say(String message){System.out.println("信息:"+message);}
}

(2)代理類[也要實現該接口,并重寫接口中的新方法,自定義新功能]

public class ProxyImpl implements SsSercive {private final SsSercive service;//構造器public ProxyImpl(SsSercive service){this.service=service;}@Overridepublic void say(String message) {System.out.println("操作前可以添加一些方法");service.say(message);System.out.println("操作后面也可以添加一些操作");}
}

(3)真正實現

public class Main {public static void main(String[] args) {SsSercive service=new ImpService();//在代理類中調用目標類ProxyImpl proxy=new ProxyImpl(service);//調用代理類中的相關方法proxy.say("hello world");}
}

運行結果:
在這里插入圖片描述

總結:
在靜態代理中,對目標類的每個方法的增強都是手動的(因為代理類實現接口要重寫各個方法),一個目標類對應一個代理類,因此十分不靈活,擴展性差。
從JVM角度來說,靜態編譯在接口中就將接口類、實現類、代理類轉化成為class文件。

動態代理

動態代理不需要為每一個目標類創建一個代理類,也可以不實現接口(CGLIB動態代理不需要實現接口)。
從JVM角度來看,動態代理是在運行時生成類字節碼,并且加載到JVM中。

JDK動態代理

JDK動態代理還是需要實現接口類Invocation,核心是Proxy代理類
(1.)接口類

public interface SsSercive {void say(String message);void send(String name);
}

實現類

public class ImpService implements SsSercive {@Overridepublic void say(String message){System.out.println("信息:"+message);}@Overridepublic void send(String name) {System.out.println("發送:"+name);}
}

(2)代理類

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
//代理類實現InvocationHandler接口
public class DebugInvocationHandler implements InvocationHandler {private Object target;public DebugInvocationHandler(Object target){this.target=target;}@Override/*proxy:是動態代理生成的代理類method:調用的相關方法args:調用方法的相關參數*/public Object invoke(Object proxy, Method method,Object[] args) throws InvocationTargetException, IllegalAccessException {System.out.println("方法之前可以添加一些功能:"+method.getName());//動態代理調用的是invoke方法,invoke方法代替我們去調用原方法Object result=method.invoke(target,args);System.out.println("方法之后可以添加一些功能:"+method.getName());return result;}
}

(3)代理對象的工廠類

import java.lang.reflect.Proxy;
public class JdkProxyFactory {
//getProxy方法的本質是調用Proxy.newProxyInstance( ),獲取某個類的代理對象public static Object getProxy(Object target){return Proxy.newProxyInstance(target.getClass().getClassLoader(),//類加載器target.getClass().getInterfaces(),//代理對象實現的接口new DebugInvocationHandler(target)//自定義實現的Invocation接口);}
}

(4)實際使用

public class Main {public static void main(String[] args) {SsSercive service=(SsSercive) JdkProxyFactory.getProxy(new ImpService());service.send("hello World");service.say("我是張三");}
}

(5)運行結果
在這里插入圖片描述

CGLIB動態代理

(1)引入依賴
說明:Spring Boot 的 parent POM(如 spring-boot-starter-parent)已經為所有常用 Spring 模塊定義好了兼容版本。顯式指定版本可能導致找不到依賴或版本沖突,所以可以不用顯示指定版本。

<dependency><groupId>org.springframework</groupId><artifactId>spring-core</artifactId></dependency>

(2)目標類

public class ImpService  {public void send(String name) {System.out.println("發送:"+name);}
}

(3)自定義方法攔截器

mport org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;import java.lang.reflect.Method;public class DebugMethodInterceptor implements MethodInterceptor {@Overridepublic Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {//調用方法之前,我們可以添加自己的操作System.out.println("before method " + method.getName());Object object = methodProxy.invokeSuper(o, args);//調用方法之后,我們同樣可以添加自己的操作System.out.println("after method " + method.getName());return object;}}

(4)代理類

import org.springframework.cglib.proxy.Enhancer;public class CglibProxyFactory {public static Object getProxy(Class<?> clazz) {// 創建動態代理增強類Enhancer enhancer = new Enhancer();// 設置類加載器enhancer.setClassLoader(clazz.getClassLoader());// 設置被代理類enhancer.setSuperclass(clazz);// 設置方法攔截器enhancer.setCallback(new DebugMethodInterceptor());// 創建代理類return enhancer.create();}
}

(5)使用

 public static void main(String[] args) {ImpService SmsService = (ImpService) CglibProxyFactory.getProxy(ImpService.class);SmsService.send("java");

(6)運行結果
在這里插入圖片描述

JDK動態代理與CGLIB動態代理的區別

(1)JDK動態代理只能直接代理接口類或是代理實現接口的類,
CGLIB動態代理可以代理不實現任何接口的類。
(2)CGLIB在運行時生成代理類的子類,不需要通過實現接口,因此不能代理聲明為final的類。

動態代理與靜態代理的區別

(1)JVM角度:靜態代理在編譯時就將接口、實現類、代理類生成class文件,
而動態代理在運行時動態生成類字節碼,并加載到jvm中。
(2)動態代理要比靜態代理更加靈活,不用必須實現接口,可直接代理。不用針對每個目標類實現一個代理類。對于目標類中方法的改動,靜態代理需要對代理類、目標對象進行修改,十分麻煩。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/88747.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/88747.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/88747.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

基于Catboost算法的茶葉數據分析及價格預測系統的設計與實現

文章目錄有需要本項目的代碼或文檔以及全部資源&#xff0c;或者部署調試可以私信博主項目介紹數據采集數據預處理數據分析與可視化大屏設計模型構建系統展示每文一語有需要本項目的代碼或文檔以及全部資源&#xff0c;或者部署調試可以私信博主 項目介紹 本研究基于京東官網…

【數據庫基礎 1】MySQL環境部署及基本操作

目錄 一、MySQL部署 1.更新軟件包列表 2.查看合適的安裝包&#xff1a; 3.安裝MySQL 4.啟動數據庫服務并設置開機自啟 5.檢測MySQL當前狀態 6.配置文件修改 二、基本操作指令 1.登陸MySQL 2.創建用戶&修改用戶密碼 3.查看版本 4.退出MySQL 5.停止MySQL 6.數據…

(C++)任務管理系統(正式版)(迭代器)(list列表基礎教程)(STL基礎知識)

源代碼&#xff1a;#include <iostream> #include <list> #include <string>using namespace std;void menu(){cout<<"\n 任務管理系統 "<<endl;cout<<"1.添加普通任務"<<endl;cout<<"2.添加緊急任務…

創建uniapp項目引入uni-id用戶體系使用beforeRegister鉤子創建默認昵稱

需求描述 基于uniCloud開發項目&#xff0c;通常會使用用戶體系&#xff0c;uni-id就是基于uniCloud的用戶體系&#xff0c;滿足常規需要的賬號密碼注冊、登錄&#xff0c;微信登錄等快捷方式&#xff0c;如果使用uni-id自帶的uni-id-pages插件&#xff0c;賬號密碼注冊的話&a…

Opencv---深度學習開發

在OpenCV中進行深度學習開發&#xff0c;主要圍繞其dnn模塊展開&#xff0c;該模塊支持加載預訓練模型、預處理輸入數據、執行推理計算以及解析輸出結果。本文講解基于OpenCV進行深度學習開發的基本流程。 一、準備工作 在開始開發前&#xff0c;需完成環境配置和資源準備&…

【C++11】右值引用詳解

文章目錄前言1. 左、右值的概念1.1 左值1.2 右值1.3 右值引用2. 右值引用的價值和使用場景2.1 左值引用的價值和缺陷2.2 右值引用的價值和使用場景2.3 小結3. 完美轉發4. 類的移動構造和移動賦值前言 在C11之前&#xff0c;面對C11之前出現的臨時對象的傳參構造&#xff0c;都…

如何用自指理解世界

自指即自我指涉&#xff0c;即自己的描述關聯到了自己&#xff0c;典型例子是“這句話是假話”這個悖論。人類對自指的研究由來已久&#xff0c;很多概念、定理都與之相關&#xff0c;由于它的巧妙性&#xff0c;很多學者對其展開了深入研究&#xff0c;并且認為自指是理解宇宙…

Next.js 實戰筆記 2.0:深入 App Router 高階特性與布局解構

Next.js 實戰筆記 2.0&#xff1a;深入 App Router 高階特性與布局解構 上一篇筆記&#xff1a; Next.js 實戰筆記 1.0&#xff1a;架構重構與 App Router 核心機制詳解 上篇筆記主要回顧了一些 Next12 到 Next15 的一些變化&#xff0c;這里繼續學習/復習一些已有或者是新的…

TCP 傳輸時 sk_buff 的 clone 和 unclone

周一有位朋友咨詢個問題&#xff0c;問題本身不重要&#xff0c;但牽扯出的細節卻是非常有趣。 Linux 內核協議棧的 skb 設計非常高效和精巧&#xff0c;多個 skb 可以指向同一塊 data&#xff0c;這就是 clone&#xff0c;當 data 不止一個 skb 指示時&#xff0c;任何一個 s…

【51單片機】51單片機學習筆記-課程簡介

00. 目錄 文章目錄00. 目錄01. 學習哪種類型的單片機02. 學習單片機方法03. 學習單片機硬件設備04. 學習單片機軟件設備05. 學完單片機能做什么06. 附錄01. 學習哪種類型的單片機 單片機的型號那么多&#xff0c;該如何選擇一款合適的進行學習呢&#xff1f;這里給讀者首推的當…

【Docker基礎】Docker端口映射(-p參數)深度解析與實踐指南

目錄 前言 1 Docker網絡基礎 1.1 Docker網絡模型概述 1.2 容器網絡隔離性 2 端口映射基礎 2.1 端口映射概念 2.2 為什么需要端口映射 3 -p參數詳解 3.1 基本語法 3.2 四種映射格式 3.2.1 完整格式 3.2.2 省略宿主機IP 3.2.3 隨機宿主機端口 3.2.4 指定協議類型 …

2、鴻蒙Harmony Next開發:ArkTS語言

目錄 什么是ArkTS&#xff1f; ArkTS的發展趨勢 ArkTS的定位及約束 ArkTS的對UI的拓展 1、UI描述 2、狀態管理&#xff1a; ArkTS語法基礎 基本知識&#xff1a;聲明 基本知識&#xff1a;類型 基本知識&#xff1a;空安全 基本知識&#xff1a;類型安全與類型推斷 …

【Elasticsearch】function_score

如果你希望在 Elasticsearch 查詢中降低某些特定 `id` 的文檔評分,可以通過 `function_score` 查詢結合 `script_score` 函數來實現。`script_score` 允許你使用自定義腳本對文檔的評分進行調整。 以下是一個示例,展示如何降低某些特定 `id` 的文檔評分: 示例場景 假設我們…

vscode打開stm32CubeIDE的項目的注釋問題

文章目錄 目的是為消除紅色底線打開命令面板&#xff1a;CtrlShiftP 搜索并打開&#xff1a;C/C: Edit Configurations (JSON) 修改并添加。&#xff08;注意里面的版本號&#xff09; {"configurations": [{"name": "Win32","includePath&…

ESP32使用freertos更新lvgl控件內容

LVGL不是線程安全&#xff0c;所有 lv_xxx方法只能在GUI主線程調用。 freertos都是線程池&#xff0c;子線程&#xff0c;不能直接更新lvgl&#xff0c;不然看門狗被觸發&#xff0c;死機。 推薦方法案例&#xff1a; 假如搜索wifi列表得到參數是wifi_options&#xff0c;需要通…

OBOO鷗柏丨滿天星(MTSTAR)多媒體信息發布系統技術解析

初次啟動歡迎您使用鷗柏(OBOO)滿天星(MTSTAR)多媒體信息發布系統&#xff0c;在使用本系統的獨立服務器模式前&#xff0c;我們需要完成設備的一些必須設置教程技術說明。其總體流程分為兩步&#xff1a;錄入本地服務器IP地址->連接網絡您獲取到的OBOO鷗柏滿天星(MTSTAR)液晶…

數據結構:棧、隊列、鏈表

目錄 棧 ?隊列 鏈表 棧 棧數據結構特點&#xff1a;先入棧的數據后出&#xff0c;此數據結構常用的方法有&#xff1a;入棧push、出棧pop、查看棧頂元素peek等&#xff0c;下方示例以數組實現棧結構。 package com.ginko.datastructure; import lombok.extern.slf4j.Slf4j…

Python-難點-uinttest

1 需求要求&#xff1a;unittest.TestCase放在列表中&#xff0c;列表存儲的是腳本文件名import使用動態加載方式&#xff1a;importlib.import_module()unittest.TestLoader使用loadTestsFromModule()2 接口3 示例4 參考資料

開源 python 應用 開發(五)python opencv之目標檢測

最近有個項目需要做視覺自動化處理的工具&#xff0c;最后選用的軟件為python&#xff0c;剛好這個機會進行系統學習。短時間學習&#xff0c;需要快速開發&#xff0c;所以記錄要點步驟&#xff0c;防止忘記。 鏈接&#xff1a; 開源 python 應用 開發&#xff08;一&#xf…

ABP VNext + OpenTelemetry + Jaeger:分布式追蹤與調用鏈可視化

ABP VNext OpenTelemetry Jaeger&#xff1a;分布式追蹤與調用鏈可視化 &#x1f680; &#x1f4da; 目錄ABP VNext OpenTelemetry Jaeger&#xff1a;分布式追蹤與調用鏈可視化 &#x1f680;背景與動機 &#x1f31f;環境與依賴 &#x1f4e6;必裝 NuGet 包系統架構概覽…