設計模式之房產中介——代理模式

手撕設計模式之房產中介——代理模式

1.業務需求

? 大家好,我是菠菜啊,好久不見,今天給大家帶來的是——代理模式。老規矩,在介紹這期內容前,我們先來看看這樣的需求:我們有一套房產需要出售,但是我們抽不開身去帶客戶看房對接而且獲客方式有限,我們該怎么實現?

在這里插入圖片描述

2.代碼實現

Talk is cheap,show me your code.

初版實現思路:

? 既然自己沒時間、沒客源,可以找個中間人不就行了,這個中間人就是房產代理。

初版代碼如下:

//房屋售賣接口
public interface HouseSaleService {void saleHouse();
}
//房東類
public class HouseOwner implements HouseSaleService {@Overridepublic void saleHouse() {System.out.println("我是房東,我簽訂售房合同");System.out.println("我是房東,售出房源");}
}
//房產中介類
public class ProxyHouse implements HouseSaleService{private HouseSaleService houseSaleService;public ProxyHouse(HouseSaleService houseSaleService) {this.houseSaleService = houseSaleService;}@Overridepublic void saleHouse() {System.out.println("房產中介——開始帶客戶看房");houseSaleService.saleHouse();System.out.println("房產中介——房源售出,結束");}
}
public class Client {public static void main(String[] args) {HouseSaleService houseSaleService = new HouseOwner();HouseSaleService proxyHouse = new ProxyHouse(houseSaleService);proxyHouse.saleHouse();}
}

輸出結果:

在這里插入圖片描述

實現代碼結構圖:

在這里插入圖片描述

這個實現過程其實就是代理設計模式,屬于代理模式中的靜態代理。

3.需求升級

我們現在不是房東了,我們現在是一個中介平臺,平臺上有千千萬萬個房東和中介,如果還是實現上述代理買房的需求,交易的流程是一樣的,該怎么做呢?不會添加那么多房產代理人吧。

//售房調用處理器類
public class HouseSaleInvocationHandler implements InvocationHandler {//房東private Object target;public HouseSaleInvocationHandler(Object target){this.target = target;}//三個參數:代理對象實例、方法對象(Method)和參數數組@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("動態生成房產中介代理——開始帶客戶看房");Object result =  method.invoke(target, args);System.out.println("動態生成房產中介代理——房源售出,結束");return result;}//創建動態代理對象public static Object newProxyInstance(Object target){//傳入目標對象的類加載器,目標對象實現的接口,調用處理器return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), new HouseSaleInvocationHandler(target));}
}
//客戶端(動態代理)
public class Client2 {public static void main(String[] args) {HouseSaleService houseSaleService = (HouseSaleService)HouseSaleInvocationHandler.newProxyInstance(new HouseOwner());houseSaleService.saleHouse();}
}

? 執行結果:

在這里插入圖片描述

? 上述代碼可以實現一套代理流程動態為多個房東生成房產代理,無需手動一個個手動創建。有沒有同學覺得很熟悉,看過jdk源碼的同學應該很熟悉(詳細實現過程見下方源碼剖析部分),它是利用java.lang.reflect包下的ProxyInvocationHandler核心類實現動態代理機制的,又稱JDK的動態代理。實現原理:在運行代碼時利用反射動態生成代理類,將目標方法的調用都轉發到InvocationHandler的invoke方法,利用反射機制執行目標方法并插入增強邏輯。

核心流程如下:

在這里插入圖片描述

思考:

? 上述代碼只能解決實現過售賣接口的房東需求,那些沒通過實現售賣接口的個人房東好像滿足不了他們的需求,所以又有另一種實現方式。

個人房東代碼改造:

pom依賴:

<dependency><groupId>cglib</groupId><artifactId>cglib</artifactId><version>3.3.0</version>
</dependency>
//cglib代理類
public class CglibProxyHouse {//獲取代理對象public static Object getInstance(Object target) {Enhancer enhancer = new Enhancer();enhancer.setSuperclass(target.getClass());// 設置目標類enhancer.setCallback(new CglibMethodInterceptor());// 設置方法攔截器return enhancer.create();}}
//cglib方法攔截增強類
public class CglibMethodInterceptor implements MethodInterceptor {@Overridepublic Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {System.out.println("動態生成房產中介代理———開始帶客戶看房-CglibProxyHouse");Object result=methodProxy.invokeSuper(proxy, args);// 調用父類(目標類)的方法System.out.println("動態生成房產中介代理———房源售出,結束-CglibProxyHouse");return result;}
}
//個人房東
public class OtherHouseOwner  {public  void saleHouse() {System.out.println("我是個人房東,我簽訂售房合同");System.out.println("我是個人房東,售出房源");}
}
//Cglib動態代理測試類
public class Client3 {public static void main(String[] args) {OtherHouseOwner houseOwner = (OtherHouseOwner)  CglibProxyHouse.getInstance(new OtherHouseOwner());houseOwner.saleHouse();}
}

運行結果:

在這里插入圖片描述

? 上述代碼實現了個人房東動態代理賣房需求,個人房東無需實現響應接口。它利用net.sf.cglib.proxy包下的EnhancerMethodInterceptor核心類實現動態代理機制的,又稱CGLIB動態代理CGLIB通過繼承目標類并重寫非final方法,在運行時使用ASM字節碼技術動態生成代理子類,將方法調用委托給MethodInterceptor實現增強邏輯,并借助FastClass機制通過方法索引直接調用提升性能。

在這里插入圖片描述

動態代理對比:

特性JDK動態代理CGLIB
代理方式實現接口繼承目標類
性能反射調用,較慢FastClass調用,較快
依賴無第三方庫需CGLIB庫
目標類要求必須實現接口不能是final類/方法
初始化開銷大(生成兩個FastClass)
方法調用模式通過InvocationHandler通過MethodInterceptor

4.定義

? 代理設計模式是一種結構型設計模式,其核心思想是提供一個代理對象來控制對原始對象的訪問。代理充當原始對象的中間層,允許在訪問原始對象前后添加額外邏輯,而無需修改原始對象本身。

組成部分如下:

  1. 代理對象(Proxy)

    • 實現與原始對象相同的接口
    • 持有對原始對象的引用
    • 控制客戶端對原始對象的訪問
  2. 原始對象(Real Subject)

    • 實際執行業務邏輯的目標對象
  3. 抽象接口(Subject)

    • 定義代理和原始對象的共同接口,確保二者可互換使用

      在這里插入圖片描述

5.應用場景

場景類型典型用途實例
虛擬代理延遲創建開銷大的對象圖片懶加載:代理先顯示占位圖,真正需要時才加載高清圖片
遠程代理隱藏遠程調用的復雜性RPC框架:代理封裝網絡通信細節,客戶端像調用本地對象一樣調用遠程服務
保護代理控制訪問權限權限校驗:代理驗證用戶權限后再允許訪問敏感操作
緩存代理緩存昂貴操作的結果API請求緩存:代理緩存計算結果,重復請求直接返回結果,避免重復計算
日志代理記錄訪問日志審計系統:代理在方法調用前后記錄日志和時間戳
智能引用代理管理對象生命周期自動釋放資源:代理統計對象引用計數,引用歸零時自動銷毀對象

適用性總結

? 需要隔離客戶端與復雜系統(如遠程服務)
? 需要延遲初始化高開銷對象
? 需添加訪問控制或安全層
? 需透明添加日志、監控等橫切關注點
? 需實現智能引用(如對象池、緩存)

典型場景:

? Spring AOP 的底層機制完全基于代理模式實現,通過動態代理在運行時生成代理對象,將切面邏輯(如日志、事務等)織入目標方法中。其具體實現分為兩種機制:JDK 動態代理CGLIB 代理,由 Spring 根據目標類的特性自動選擇或通過配置強制指定。目標類實現了接口,使用JDK 動態代理;目標類未實現接口,CGLIB 代理,也可強制指定。

源碼剖析

1.JDK動態代理

1.1 Proxy.newProxyInstance() 入口方法
public static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h) {// 1. 驗證接口和處理器有效性Objects.requireNonNull(h);final Class<?>[] intfs = interfaces.clone();// 2. 獲取或生成代理類Class<?> cl = getProxyClass0(loader, intfs);try {// 3. 獲取代理類構造器final Constructor<?> cons = cl.getConstructor(constructorParams);// 4. 創建代理實例return cons.newInstance(new Object[]{h});} catch (IllegalAccessException|InstantiationException e) {// 異常處理...}
}
1.2 代理類生成機制(getProxyClass0)
private static Class<?> getProxyClass0(ClassLoader loader,Class<?>... interfaces) {// 1. 接口數量限制(最多65535個)if (interfaces.length > 65535) {throw new IllegalArgumentException("interface limit exceeded");}// 2. 從緩存獲取或生成代理類return proxyClassCache.get(loader, interfaces);
}

代理類緩存使用WeakCache實現,核心邏輯在ProxyClassFactory中:

private static final class ProxyClassFactoryimplements BiFunction<ClassLoader, Class<?>[], Class<?>>
{@Overridepublic Class<?> apply(ClassLoader loader, Class<?>[] interfaces) {// 1. 生成唯一代理類名long num = nextUniqueNumber.getAndIncrement();String proxyName = proxyPkg + proxyClassNamePrefix + num;// 2. 生成代理類字節碼byte[] proxyClassFile = ProxyGenerator.generateProxyClass(proxyName, interfaces, accessFlags);// 3. 定義代理類return defineClass0(loader, proxyName,proxyClassFile, 0, proxyClassFile.length);}
}
1.3 代理類字節碼生成(ProxyGenerator)

generateProxyClass方法生成代理類的字節碼,其核心邏輯如下:

public static byte[] generateProxyClass(final String name,Class<?>[] interfaces,int accessFlags) {ProxyGenerator gen = new ProxyGenerator(name, interfaces, accessFlags);// 真正生成字節碼final byte[] classFile = gen.generateClassFile();// 可選項:保存生成的字節碼到文件(調試用)if (saveGeneratedFiles) {java.security.AccessController.doPrivileged(new java.security.PrivilegedAction<Void>() {public Void run() {try {FileOutputStream file = new FileOutputStream(dotToSlash(name) + ".class");file.write(classFile);file.close();} catch (IOException e) { /* 忽略 */ }return null;}});}return classFile;
}
1.4 生成的代理類結構(反編譯示例)

假設我們代理HouseSaleService接口,生成的$Proxy0.class反編譯后:

public final class $Proxy0 extends Proxy implements HouseSaleService {private static Method m1;  // hashCode()private static Method m2;  // equals()private static Method m3;  // toString()private static Method m4;  // saleHouse()static {try {m1 = Class.forName("java.lang.Object").getMethod("hashCode");m2 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));m3 = Class.forName("java.lang.Object").getMethod("toString");m4 = Class.forName("com.example.HouseSaleService").getMethod("saleHouse");} catch (NoSuchMethodException e) { /* 處理異常 */ }}public $Proxy0(InvocationHandler h) {super(h);  // 調用Proxy的構造函數}public final void saleHouse() {try {// 關鍵:調用InvocationHandler的invoke方法super.h.invoke(this, m4, null);} catch (RuntimeException | Error e) {throw e;} catch (Throwable e) {throw new UndeclaredThrowableException(e);}}// 其他Object方法實現類似...
}

代理對象實現目標接口,方法調用里其實還是調用InvocationHandler的invoke方法。

2.CGLIB動態代理

2.1Enhancer 入口類

創建代理對象通常使用以下代碼:

Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(TargetClass.class); // 設置目標類
enhancer.setCallback(new MyMethodInterceptor()); // 設置回調(攔截器)
TargetClass proxy = (TargetClass) enhancer.create(); // 生成代理對象
2.2 enhancer.create() 方法調用鏈
// Enhancer.java
public Object create() {// 關鍵:不使用參數return createHelper();
}private Object createHelper() {// 1. 驗證回調類型preValidate();// 2. 生成代理類Class<?> proxyClass = createClass();// 3. 創建代理實例return createUsingReflection(proxyClass);
}
2.3 代理類生成(createClass)
// AbstractClassGenerator.java
protected Class<?> createClass() {// 使用字節碼生成器生成字節碼byte[] b = strategy.generate(this);// 定義類return ReflectUtils.defineClass(getClassName(), b, loader);
}
2.4 字節碼生成核心:Enhancer.generateClass

CGLIB通過ASM庫直接操作字節碼,關鍵邏輯在Enhancer.generateClass方法中:

// Enhancer.java
public void generateClass(ClassVisitor v) {// 1. 創建類結構ClassEmitter ce = new ClassEmitter(v);ce.begin_class(/* 版本號 */, ACC_PUBLIC, getClassName(), getSuperclass(), getInterfaces(), "<generated>");// 2. 添加字段ce.declare_field(ACC_PRIVATE, BOUND_FIELD, Type.BOOLEAN_TYPE, null);ce.declare_field(ACC_PRIVATE, THREAD_CALLBACKS_FIELD, THREAD_LOCAL, null);ce.declare_field(ACC_PRIVATE, STATIC_CALLBACKS_FIELD, CALLBACK_ARRAY, null);// 3. 生成構造函數generateConstructor(ce);// 4. 生成回調設置方法generateSetCallbacks(ce);generateSetCallback(ce);generateGetCallback(ce);// 5. 重寫目標方法for (Method method : getMethods()) {generateMethod(ce, method);}ce.end_class();
}
2.5 方法生成邏輯(generateMethod)
// Enhancer.java
private void generateMethod(ClassEmitter ce, Method method) {// 1. 創建方法簽名Signature sig = ReflectUtils.getSignature(method);// 2. 創建方法體CodeEmitter e = ce.begin_method(ACC_PUBLIC, sig, null);// 3. 獲取回調e.load_this();e.getfield(CALLBACK_FIELD);// 4. 檢查回調是否存在Label noCallback = e.make_label();e.dup();e.ifnull(noCallback);// 5. 準備調用參數e.push(method);e.create_arg_array();e.push(methodProxy);// 6. 調用攔截器e.invoke_interface(METHOD_INTERCEPTOR_TYPE, new Signature("intercept", Type.OBJECT, new Type[]{TYPE_OBJECT, TYPE_METHOD, TYPE_OBJECT_ARRAY, TYPE_METHOD_PROXY}));// 7. 結果處理e.unbox_or_zero(e.getReturnType());e.return_value();// 8. 沒有回調時的處理e.mark(noCallback);e.pop();// 調用原始方法super.generateMethod(ce, method);e.return_value();e.end_method();
}
2.6 生成的代理類結構(反編譯示例)

使用CGLIB代理后生成的代理類大致如下:

public class OtherHouseOwner$$EnhancerByCGLIB$$12345678 extends OtherHouseOwner implements Factory {private MethodInterceptor interceptor;private static final Method CGLIB$saleHouse$0$Method;private static final MethodProxy CGLIB$saleHouse$0$Proxy;static {// 初始化目標方法和代理方法CGLIB$saleHouse$0$Method = ReflectUtils.findMethods(new String[]{"saleHouse", "()V"}).get(0);CGLIB$saleHouse$0$Proxy = MethodProxy.create(OtherHouseOwner.class, OtherHouseOwner$$EnhancerByCGLIB$$12345678.class, "()V", "saleHouse", "CGLIB$saleHouse$0");}// 重寫目標方法public final void saleHouse() {MethodInterceptor tmp = this.interceptor;if (tmp == null) {super.saleHouse(); // 如果未設置攔截器,直接調用父類方法} else {// 調用攔截器的intercept方法tmp.intercept(this, CGLIB$saleHouse$0$Method, new Object[0], CGLIB$saleHouse$0$Proxy);}}// 原始方法的直接調用(避免攔截)final void CGLIB$saleHouse$0() {super.saleHouse();}// 其他方法...
}

如果未設置攔截器,直接調用父類方法;如果有設置方法攔截器,直接回調攔截器方法。

2.7 MethodProxy 工作原理

MethodProxy是CGLIB高效調用的關鍵,它通過生成兩個FastClass(目標類FastClass和代理類FastClass)實現快速方法調用。

// MethodProxy.java
public Object invoke(Object obj, Object[] args) throws Throwable {try {// 使用目標類的FastClass直接調用原始方法return fastClass.invoke(targetIndex, obj, args);} catch (InvocationTargetException e) {throw e.getTargetException();}
}public Object invokeSuper(Object obj, Object[] args) throws Throwable {try {// 使用代理類的FastClass調用代理類中的原始方法(即CGLIB$xxx方法)return fastClass.invoke(superIndex, obj, args);} catch (InvocationTargetException e) {throw e.getTargetException();}
}
2.8 FastClass 機制

FastClass為每個方法分配一個索引(index),通過索引直接調用方法,避免反射開銷。

// 生成的TargetFastClass
public Object invoke(int index, Object obj, Object[] args) {OtherHouseOwner otherHouseOwner = (OtherHouseOwner) obj;switch (index) {case 0:otherHouseOwner.saleHouse();return null;// 其他方法...}
}// 生成的ProxyFastClass
public Object invoke(int index, Object obj, Object[] args) {OtherHouseOwner$$EnhancerByCGLIB proxy = (OtherHouseOwner$$EnhancerByCGLIB) obj;switch (index) {case 0:proxy.CGLIB$saleHouse$0();return null;// 其他方法...}
}

法,避免反射開銷。

// 生成的TargetFastClass
public Object invoke(int index, Object obj, Object[] args) {OtherHouseOwner otherHouseOwner = (OtherHouseOwner) obj;switch (index) {case 0:otherHouseOwner.saleHouse();return null;// 其他方法...}
}// 生成的ProxyFastClass
public Object invoke(int index, Object obj, Object[] args) {OtherHouseOwner$$EnhancerByCGLIB proxy = (OtherHouseOwner$$EnhancerByCGLIB) obj;switch (index) {case 0:proxy.CGLIB$saleHouse$0();return null;// 其他方法...}
}

技術需要沉淀,同樣生活也是~
個人鏈接:博客,歡迎一起交流

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

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

相關文章

Unity進階課程【六】Android、ios、Pad 終端設備打包局域網IP調試、USB調試、性能檢測、控制臺打印日志等、C#

Unity打包 Android、ios、Pad 終端設備局域網IP調試、USB調試 今天咱們繼續進階課程&#xff0c;定期更新&#xff0c;有想學習的不懂的地方也可以告訴我。 提示&#xff1a;內容純個人編寫&#xff0c;歡迎評論點贊&#xff0c;來指正我。 文章目錄 Unity打包 Android、ios、P…

c++中的mutex同步機制與多線程同步實現

C 中的 std::mutex 與多線程同步 在多線程編程中&#xff0c;互斥鎖&#xff08;Mutex&#xff09; 是一種同步機制&#xff0c;用于保護共享資源&#xff08;如變量、數據結構&#xff09;免受數據競爭&#xff08;Data Race&#xff09;的影響。C 標準庫中的 std::mutex 提供…

網絡安全2023—新安全新發展

關于綠盟科技 綠盟科技集團股份有限公司(以下簡稱綠盟科技),成立于 2000 年 4 月,總部位于北京。公司于 2014 年 1 月 29 日在深圳證券交易所創業板上市,證券代碼:300369。綠盟科技在國內設有 50余個分支機構,為政府、金融、運營商、能源、交通、科教文衛等行業用戶與各…

WebSocket掃盲

WebSocket 是一種網絡通信協議&#xff0c;它允許在單個 TCP 連接上進行全雙工、雙向的實時通信。它是為了解決傳統 HTTP 協議在實時交互應用中的局限性而設計的。 核心概念和特點 解決 HTTP 的痛點&#xff1a; 單向性&#xff1a; HTTP 是請求-響應模式。客戶端發起請求&…

Springboot整合高德地圖

1.登錄高德開放平臺 高德開放平臺 | 高德地圖API 2.獲取密鑰key 1.點擊控制臺 2.創建新應用 3.添加key 4.創建key 5.獲取key 3.java整合 1.高德配置類 package com.thk.controller.map;import org.springframework.beans.factory.annotation.Value; import org.springfram…

【SQL知識】PDO 和 MySQLi 的區別

目錄 簡介 主要區別 預處理語句示例比較 PDO 示例 MySQLi 示例 選擇建議 簡介 PDO (PHP Data Objects) 和 MySQLi (MySQL Improved) 都是 PHP 中用于數據庫操作的擴展&#xff0c;都支持預處理語句&#xff0c;但有一些重要區別&#xff1a; 主要區別 數據庫支持 PDO&am…

python打卡 DAY 45 Tensorboard使用介紹

目錄 一、TensorBoard 發展歷史與原理 1. 演進歷程 2. 核心架構原理 二、TensorBoard 核心功能操作 1. 基礎配置方法 2. 常用功能速查表 三、CIFAR10 實戰演示 1. MLP 模型監控配置 2. CNN 特征可視化 四、TensorBoard 高級功能 1. 超參數調優 2. 3D點云可視化 五、…

Swift 中 Result 類型全解析:從基礎到進階

在現代 iOS 開發中&#xff0c;Swift 的 Result 類型是處理同步與異步錯誤的一大利器。相比傳統的 throws / do-catch 語法&#xff0c;它更清晰、結構化&#xff0c;也更易于組合式編程。 本文將帶你從 Result 的基礎定義出發&#xff0c;逐步深入其在實際項目中的多種應用&am…

Github 2025-06-28 Rust開源項目日報 Top10

根據Github Trendings的統計,今日(2025-06-28統計)共有10個項目上榜。根據開發語言中項目的數量,匯總情況如下: 開發語言項目數量Rust項目10Rust實現的非官方Bitwarden兼容服務器 創建周期:2317 天開發語言:Rust協議類型:GNU Affero General Public License v3.0Star數量…

python 寫一個判斷文本中是否有手機號的函數,并提取出文本中的手機號

我們需要判斷文本中是否有手機號&#xff0c;并提取出手機號。 中國大陸的手機號規則&#xff1a; 1. 通常為11位數字。 2. 目前手機號段分配如下&#xff1a; - 移動號段&#xff1a;134(0-8)、135、136、137、138、139、147、148、150、151、152、157、158、159、172、178、1…

作物生長模型Oryza V3實戰12:drate程序詳解

drate(v2).exe,可以通過觀察移植日、穗部分化、開花和成熟的物候日期(即日和年),DRATE(v2)用于校準四個階段的發展速率:幼苗期(DVRJ,oCday-1)、光周期敏感期(DVRI,oCday-1)、穗部發育期(DVRP,oCday-1)和生殖期(DVRR,oCday-1)。 一 準備輸入文件 1、準備.crp,.…

利用視覺-語言模型搭建機器人靈巧操作的支架

25年6月來自斯坦福和德國卡爾斯魯厄理工的論文“Scaffolding Dexterous Manipulation with Vision-Language Models”。 靈巧機械手對于執行復雜的操作任務至關重要&#xff0c;但由于演示收集和高維控制的挑戰&#xff0c;其訓練仍然困難重重。雖然強化學習 (RL) 可以通過在模…

面試拷打-20250701

memcopy和memmov 詳細解釋 示例1&#xff1a;不重疊的內存區域 正常復制。 示例2&#xff1a;重疊的內存區域 原始數據&#xff1a;src2是一個包含字符串"HelloWorld"的字符數組。使用memcpy&#xff1a; memcpy(src2 2, src2, 5);試圖將src2中的前5個字符復制…

什么是 BigKey?

Redis BigKey 深度解析&#xff1a;識別、危害與優化方案 什么是 BigKey&#xff1f; 在 Redis 中&#xff0c;BigKey 是指存儲大量數據的單個鍵&#xff0c;這些鍵通常具有異常大的內存占用或包含大量元素。BigKey 不是由數據類型定義&#xff0c;而是由其資源消耗決定的。 …

量化選股策略 聚寬

# 量化選股策略完整分析與優化建議 ## 策略整體架構分析 這個量化交易策略主要由以下幾個核心部分組成&#xff1a; 1. **初始化設置**&#xff1a;配置基準指數、交易參數和全局變量 2. **選股邏輯**&#xff1a;通過財務指標篩選優質股票 3. **股票過濾**&#xff1a;排除…

Python 數據分析:numpy,抽提,布爾索引2。

目錄 1 示例代碼2 歡迎糾錯3 論文寫作/Python 學習智能體------以下關于 Markdown 編輯器新的改變功能快捷鍵合理的創建標題&#xff0c;有助于目錄的生成如何改變文本的樣式插入鏈接與圖片如何插入一段漂亮的代碼片生成一個適合你的列表創建一個表格設定內容居中、居左、居右S…

解決leetcode第3597題分割字符串

3597. 分割字符串 難度&#xff1a;中等 問題描述&#xff1a; 給你一個字符串 s&#xff0c;按照以下步驟將其分割為 互不相同的段 &#xff1a; 從下標 0 開始構建一個段。 逐字符擴展當前段&#xff0c;直到該段之前未曾出現過。 只要當前段是唯一的&#xff0c;就將其…

電源芯片之DCDC初探索ING

1. 概述 DC-DC轉換器的意思是直流變直流&#xff08;不同的直流電源值得轉換&#xff09;&#xff0c;是一種在直流電路中將一個電壓值的電能變為另一個電壓值的電能裝置。 DC-DC轉換器一般由控制芯片、電感線圈、二極管、三極管、電容器構成。 2. 基本拓撲結構 2.1 非隔離…

JavaEE:分布式session

一、使用Redis存儲分布式session&#xff1a; 1.SpringBoot整合Redis&#xff0c;見如下地址&#xff1a; JavaEE&#xff1a;SpringBoot整合Redis_a526001650a-CSDN博客 2.代碼實現分布式session存儲(此處以token為例)&#xff1a; Autowired private RedisTemplate<St…

OpenCV CUDA模塊設備層-----“大于閾值設為零” 的圖像處理函數 thresh_to_zero_inv_func()

操作系統&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 編程語言&#xff1a;C11 算法描述 OpenCV 的 CUDA 模塊&#xff08;cudev&#xff09; 中的一個仿函數生成器&#xff0c;用于創建一個 “大于閾值設為零” 的圖像處理函數對象。 …