From 8c81e43a071a74c4b44a96750a614167050c7193 Mon Sep 17 00:00:00 2001 From: Looly Date: Thu, 2 Jan 2025 13:33:02 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8DProxyUtil=E5=8F=AF=E8=83=BD?= =?UTF-8?q?=E7=9A=84=E7=A9=BA=E6=8C=87=E9=92=88=E9=97=AE=E9=A2=98=EF=BC=88?= =?UTF-8?q?issue#IBF20Z@Gitee=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 3 +- .../cn/hutool/aop/proxy/JdkProxyFactory.java | 5 ++ .../cn/hutool/aop/proxy/ProxyFactory.java | 8 ++- .../cn/hutool/aop/test/IssueIBF20ZTest.java | 49 +++++++++++++++++++ 4 files changed, 63 insertions(+), 2 deletions(-) create mode 100644 hutool-aop/src/test/java/cn/hutool/aop/test/IssueIBF20ZTest.java diff --git a/CHANGELOG.md b/CHANGELOG.md index 83cf0736a..36d0cb044 100755 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,11 +2,12 @@ # 🚀Changelog ------------------------------------------------------------------------------------------------------------- -# 5.8.36(2025-01-01) +# 5.8.36(2025-01-02) ### 🐣新特性 * 【crypto 】 增加BCUtil.decodeECPrivateKey方法(issue#3829@Github) ### 🐞Bug修复 +* 【aop 】 修复ProxyUtil可能的空指针问题(issue#IBF20Z@Gitee) ------------------------------------------------------------------------------------------------------------- # 5.8.35(2024-12-25) diff --git a/hutool-aop/src/main/java/cn/hutool/aop/proxy/JdkProxyFactory.java b/hutool-aop/src/main/java/cn/hutool/aop/proxy/JdkProxyFactory.java index 91a5a7129..166b45e2a 100755 --- a/hutool-aop/src/main/java/cn/hutool/aop/proxy/JdkProxyFactory.java +++ b/hutool-aop/src/main/java/cn/hutool/aop/proxy/JdkProxyFactory.java @@ -12,6 +12,11 @@ import cn.hutool.aop.interceptor.JdkInterceptor; public class JdkProxyFactory extends ProxyFactory { private static final long serialVersionUID = 1L; + /** + * 获取单例 + */ + public static JdkProxyFactory INSTANCE = new JdkProxyFactory(); + @Override public T proxy(T target, Aspect aspect) { return ProxyUtil.newProxyInstance(// diff --git a/hutool-aop/src/main/java/cn/hutool/aop/proxy/ProxyFactory.java b/hutool-aop/src/main/java/cn/hutool/aop/proxy/ProxyFactory.java index 96d988971..db45b9d45 100755 --- a/hutool-aop/src/main/java/cn/hutool/aop/proxy/ProxyFactory.java +++ b/hutool-aop/src/main/java/cn/hutool/aop/proxy/ProxyFactory.java @@ -59,7 +59,13 @@ public abstract class ProxyFactory implements Serializable { * @return 代理对象 */ public static T createProxy(T target, Aspect aspect) { - return create().proxy(target, aspect); + ProxyFactory factory = create(); + if(null == factory){ + // issue#IBF20Z + // 可能的空指针问题 + factory = JdkProxyFactory.INSTANCE; + } + return factory.proxy(target, aspect); } /** diff --git a/hutool-aop/src/test/java/cn/hutool/aop/test/IssueIBF20ZTest.java b/hutool-aop/src/test/java/cn/hutool/aop/test/IssueIBF20ZTest.java new file mode 100644 index 000000000..22a246809 --- /dev/null +++ b/hutool-aop/src/test/java/cn/hutool/aop/test/IssueIBF20ZTest.java @@ -0,0 +1,49 @@ +package cn.hutool.aop.test; + +import cn.hutool.aop.proxy.ProxyFactory; +import cn.hutool.core.lang.Console; +import cn.hutool.core.thread.ThreadUtil; +import org.junit.jupiter.api.Test; + +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.atomic.AtomicInteger; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class IssueIBF20ZTest { + + @Test + public void testLoadFirstAvailableConcurrent() throws InterruptedException { + // 创建一个固定大小的线程池 + int threadCount = 1000; + ExecutorService executorService = ThreadUtil.newExecutor(threadCount); + + // 创建一个 CountDownLatch,用于等待所有任务完成 + CountDownLatch latch = new CountDownLatch(threadCount); + + // 计数器用于统计成功加载服务提供者的次数 + AtomicInteger successCount = new AtomicInteger(0); + + // 提交多个任务到线程池 + for (int i = 0; i < threadCount; i++) { + executorService.submit(() -> { + ProxyFactory factory = ProxyFactory.create(); + if (factory != null) { + Console.log(factory.getClass()); + successCount.incrementAndGet(); + } + latch.countDown(); // 每个任务完成时,计数减一 + }); + } + + // 等待所有任务完成 + latch.await(); + + // 关闭线程池并等待所有任务完成 + executorService.shutdown(); + + // 验证所有线程都成功加载了服务提供者 + assertEquals(threadCount, successCount.get()); + } +}