diff --git a/common/src/main/java/org/dromara/dynamictp/common/entity/ThreadPoolStats.java b/common/src/main/java/org/dromara/dynamictp/common/entity/ThreadPoolStats.java index c294765b5..06b4928b1 100644 --- a/common/src/main/java/org/dromara/dynamictp/common/entity/ThreadPoolStats.java +++ b/common/src/main/java/org/dromara/dynamictp/common/entity/ThreadPoolStats.java @@ -51,6 +51,11 @@ public class ThreadPoolStats extends Metrics { */ private int maximumPoolSize; + /** + * 空闲时间 (ms) + */ + private long keepAliveTime; + /** * 队列类型 */ diff --git a/core/src/main/java/org/dromara/dynamictp/core/aware/AwareManager.java b/core/src/main/java/org/dromara/dynamictp/core/aware/AwareManager.java index 28feee7dc..98cb34184 100644 --- a/core/src/main/java/org/dromara/dynamictp/core/aware/AwareManager.java +++ b/core/src/main/java/org/dromara/dynamictp/core/aware/AwareManager.java @@ -96,7 +96,7 @@ public static void execute(Executor executor, Runnable r) { public static void beforeExecute(Executor executor, Thread t, Runnable r) { for (ExecutorAware aware : EXECUTOR_AWARE_LIST) { try { - aware.beforeExecute(executor, t, r); + r = aware.beforeExecuteWrap(executor, t, r); } catch (Exception e) { log.error("DynamicTp aware [{}], enhance beforeExecute error.", aware.getName(), e); } @@ -106,7 +106,7 @@ public static void beforeExecute(Executor executor, Thread t, Runnable r) { public static void afterExecute(Executor executor, Runnable r, Throwable t) { for (ExecutorAware aware : EXECUTOR_AWARE_LIST) { try { - aware.afterExecute(executor, r, t); + r = aware.afterExecuteWrap(executor, r, t); } catch (Exception e) { log.error("DynamicTp aware [{}], enhance afterExecute error.", aware.getName(), e); } @@ -146,7 +146,7 @@ public static void terminated(Executor executor) { public static void beforeReject(Runnable r, Executor executor) { for (ExecutorAware aware : EXECUTOR_AWARE_LIST) { try { - aware.beforeReject(r, executor); + r = aware.beforeRejectWrap(r, executor); } catch (Exception e) { log.error("DynamicTp aware [{}], enhance beforeReject error.", aware.getName(), e); } @@ -156,7 +156,7 @@ public static void beforeReject(Runnable r, Executor executor) { public static void afterReject(Runnable r, Executor executor) { for (ExecutorAware aware : EXECUTOR_AWARE_LIST) { try { - aware.afterReject(r, executor); + r = aware.afterRejectWrap(r, executor); } catch (Exception e) { log.error("DynamicTp aware [{}], enhance afterReject error.", aware.getName(), e); } diff --git a/core/src/main/java/org/dromara/dynamictp/core/aware/ExecutorAware.java b/core/src/main/java/org/dromara/dynamictp/core/aware/ExecutorAware.java index 29af266b2..56e492bf1 100644 --- a/core/src/main/java/org/dromara/dynamictp/core/aware/ExecutorAware.java +++ b/core/src/main/java/org/dromara/dynamictp/core/aware/ExecutorAware.java @@ -91,6 +91,11 @@ default void beforeExecute(Executor executor, Thread t, Runnable r) { // default no Operation } + default Runnable beforeExecuteWrap(Executor executor, Thread t, Runnable r) { + beforeExecute(executor, t, r); + return r; + } + /** * enhance afterExecute * @@ -102,6 +107,11 @@ default void afterExecute(Executor executor, Runnable r, Throwable t) { // default no Operation } + default Runnable afterExecuteWrap(Executor executor, Runnable r, Throwable t) { + afterExecute(executor, r, t); + return r; + } + /** * enhance shutdown * @@ -139,6 +149,11 @@ default void beforeReject(Runnable r, Executor executor) { // default no Operation } + default Runnable beforeRejectWrap(Runnable r, Executor executor) { + beforeReject(r, executor); + return r; + } + /** * enhance after reject * @param r runnable @@ -147,4 +162,9 @@ default void beforeReject(Runnable r, Executor executor) { default void afterReject(Runnable r, Executor executor) { // default no Operation } + + default Runnable afterRejectWrap(Runnable r, Executor executor) { + afterReject(r, executor); + return r; + } } diff --git a/core/src/main/java/org/dromara/dynamictp/core/converter/ExecutorConverter.java b/core/src/main/java/org/dromara/dynamictp/core/converter/ExecutorConverter.java index 70af16371..48d333321 100644 --- a/core/src/main/java/org/dromara/dynamictp/core/converter/ExecutorConverter.java +++ b/core/src/main/java/org/dromara/dynamictp/core/converter/ExecutorConverter.java @@ -97,6 +97,7 @@ private static ThreadPoolStats convertCommon(ExecutorAdapter executor) { poolStats.setCompletedTaskCount(executor.getCompletedTaskCount()); poolStats.setWaitTaskCount(executor.getQueueSize()); poolStats.setRejectHandlerName(executor.getRejectHandlerType()); + poolStats.setKeepAliveTime(executor.getKeepAliveTime(TimeUnit.MILLISECONDS)); return poolStats; } } diff --git a/core/src/main/java/org/dromara/dynamictp/core/monitor/collector/jmx/JMXCollector.java b/core/src/main/java/org/dromara/dynamictp/core/monitor/collector/jmx/JMXCollector.java index a7643b2b7..366aab465 100644 --- a/core/src/main/java/org/dromara/dynamictp/core/monitor/collector/jmx/JMXCollector.java +++ b/core/src/main/java/org/dromara/dynamictp/core/monitor/collector/jmx/JMXCollector.java @@ -21,14 +21,11 @@ import org.dromara.dynamictp.common.em.CollectorTypeEnum; import org.dromara.dynamictp.common.entity.ThreadPoolStats; import org.dromara.dynamictp.core.monitor.collector.AbstractCollector; -import org.springframework.beans.BeanUtils; import javax.management.JMException; import javax.management.MBeanServer; import javax.management.ObjectName; import java.lang.management.ManagementFactory; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; /** * ThreadPoolStatsInfo related @@ -40,26 +37,15 @@ public class JMXCollector extends AbstractCollector { public static final String DTP_METRIC_NAME_PREFIX = "dtp.thread.pool"; - /** - * thread pool stats map - */ - private static final Map GAUGE_CACHE = new ConcurrentHashMap<>(); - @Override public void collect(ThreadPoolStats threadPoolStats) { - if (GAUGE_CACHE.containsKey(threadPoolStats.getPoolName())) { - ThreadPoolStats poolStats = GAUGE_CACHE.get(threadPoolStats.getPoolName()); - BeanUtils.copyProperties(threadPoolStats, poolStats); - } else { - try { - MBeanServer server = ManagementFactory.getPlatformMBeanServer(); - ObjectName name = new ObjectName(DTP_METRIC_NAME_PREFIX + ":name=" + threadPoolStats.getPoolName()); - ThreadPoolStatsJMX stats = new ThreadPoolStatsJMX(threadPoolStats); - server.registerMBean(stats, name); - } catch (JMException e) { - log.error("collect thread pool stats error", e); - } - GAUGE_CACHE.put(threadPoolStats.getPoolName(), threadPoolStats); + try { + MBeanServer server = ManagementFactory.getPlatformMBeanServer(); + ObjectName name = new ObjectName(DTP_METRIC_NAME_PREFIX + ":name=" + threadPoolStats.getPoolName()); + ThreadPoolStatsJMX stats = new ThreadPoolStatsJMX(threadPoolStats); + server.registerMBean(stats, name); + } catch (JMException e) { + log.error("collect thread pool stats error", e); } } diff --git a/dependencies/pom.xml b/dependencies/pom.xml index 3cc5d53bf..ba00b1c4e 100644 --- a/dependencies/pom.xml +++ b/dependencies/pom.xml @@ -12,7 +12,7 @@ https://github.com/yanhom1314/dynamic-tp - 1.1.7 + 1.1.8-beta UTF-8 1.18.24 @@ -426,6 +426,12 @@ ${revision} + + org.dromara.dynamictp + dynamic-tp-extension-agent + ${revision} + + org.dromara.dynamictp dynamic-tp-extension-notify-email diff --git a/extension/extension-agent/pom.xml b/extension/extension-agent/pom.xml new file mode 100644 index 000000000..26585b894 --- /dev/null +++ b/extension/extension-agent/pom.xml @@ -0,0 +1,14 @@ + + 4.0.0 + + org.dromara.dynamictp + dynamic-tp-extension + ${revision} + ../pom.xml + + dynamic-tp-extension-agent + + + + diff --git a/extension/extension-agent/src/main/java/org/dromara/dynamictp/core/aware/AgentAware.java b/extension/extension-agent/src/main/java/org/dromara/dynamictp/core/aware/AgentAware.java new file mode 100644 index 000000000..f456db816 --- /dev/null +++ b/extension/extension-agent/src/main/java/org/dromara/dynamictp/core/aware/AgentAware.java @@ -0,0 +1,151 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.dromara.dynamictp.core.aware; + +import cn.hutool.core.util.ArrayUtil; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.collections4.CollectionUtils; +import org.dromara.dynamictp.core.support.task.runnable.DtpRunnable; + +import java.lang.ref.SoftReference; +import java.lang.reflect.Field; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.Executor; +import java.util.stream.Collectors; + +import static org.dromara.dynamictp.common.constant.DynamicTpConst.DTP_EXECUTE_ENHANCED; +import static org.dromara.dynamictp.common.constant.DynamicTpConst.FALSE_STR; + +/** + * deal agent wrapper + * @author txbao + */ +@Slf4j +@SuppressWarnings("all") +public class AgentAware extends TaskStatAware { + + /** + * dtpRunnableCache key -> Runnable value -> DtpRunnable + */ + private final Map> dtpRunnableCache = new ConcurrentHashMap<>(); + + @Override + public int getOrder() { + return Integer.MIN_VALUE; + } + + @Override + public String getName() { + return "agent"; + } + + private DtpRunnable determineDtpRunnable(List conditionalFields, Runnable r) throws IllegalAccessException { + for (Field field : conditionalFields) { + if (Objects.isNull(field)) { + continue; + } + field.setAccessible(true); + Runnable o = (Runnable) field.get(r); + if (o instanceof DtpRunnable) { + return (DtpRunnable) o; + } + // 纵向查找 + DtpRunnable dtpRunnable = getDtpRunnable(o.getClass(), o); + if (dtpRunnable != null) { + return dtpRunnable; + } + } + return null; + } + + private DtpRunnable getDtpRunnable(Class rClass, Runnable r) throws IllegalAccessException { + while (Runnable.class.isAssignableFrom(rClass)) { + Field[] declaredFields = rClass.getDeclaredFields(); + if (ArrayUtil.isNotEmpty(declaredFields)) { + List conditionFields = Arrays.stream(declaredFields) + .filter(ele -> Runnable.class.isAssignableFrom(ele.getType())) + .collect(Collectors.toList()); + if (CollectionUtils.isNotEmpty(conditionFields)) { + DtpRunnable dtpRunnable = determineDtpRunnable(conditionFields, r); + if (Objects.nonNull(dtpRunnable)) { + return dtpRunnable; + } + } + } + if (!Runnable.class.isAssignableFrom(rClass.getSuperclass())) { + break; + } + rClass = (Class) rClass.getSuperclass(); + } + return null; + } + + private Runnable getDtpRunnableInstance(Runnable r) { + if (r instanceof DtpRunnable) { + return r; + } + DtpRunnable dtpRunnable = null; + Class rClass = r.getClass(); + try { + dtpRunnable = getDtpRunnable(rClass, r); + } catch (IllegalAccessException e) { + log.error("getDtpRunnable Error", e); + } + if (dtpRunnable == null) { + if (log.isWarnEnabled()) { + log.warn("DynamicTp aware [{}], can not find DtpRunnable.", getName()); + } + return r; + } + return dtpRunnable; + } + + @Override + public Runnable beforeExecuteWrap(Executor executor, Thread t, Runnable r) { + Runnable runnableWrap = getDtpRunnableInstance(r); + if (runnableWrap instanceof DtpRunnable) { + dtpRunnableCache.put(r, new SoftReference<>((DtpRunnable) runnableWrap)); + } else { + // 被封装的wrapper没有找到DtpRunnable对象,那么就关闭某些监控指标,防止内存溢出 + System.setProperty(DTP_EXECUTE_ENHANCED, FALSE_STR); + } + return runnableWrap; + } + + @Override + public Runnable afterExecuteWrap(Executor executor, Runnable r, Throwable t) { + SoftReference remove = dtpRunnableCache.remove(r); + if (remove != null) { + return remove.get(); + } + return getDtpRunnableInstance(r); + } + + @Override + public Runnable beforeRejectWrap(Runnable r, Executor executor) { + SoftReference remove = dtpRunnableCache.remove(r); + if (remove != null) { + return remove.get(); + } + return getDtpRunnableInstance(r); + } +} diff --git a/extension/extension-agent/src/main/resources/META-INF/services/org.dromara.dynamictp.core.aware.ExecutorAware b/extension/extension-agent/src/main/resources/META-INF/services/org.dromara.dynamictp.core.aware.ExecutorAware new file mode 100644 index 000000000..064e5f138 --- /dev/null +++ b/extension/extension-agent/src/main/resources/META-INF/services/org.dromara.dynamictp.core.aware.ExecutorAware @@ -0,0 +1 @@ +org.dromara.dynamictp.core.aware.AgentAware \ No newline at end of file diff --git a/extension/extension-skywalking/pom.xml b/extension/extension-skywalking/pom.xml index 70fb7469e..019485e91 100644 --- a/extension/extension-skywalking/pom.xml +++ b/extension/extension-skywalking/pom.xml @@ -21,11 +21,6 @@ org.slf4j slf4j-api - - - org.dromara.dynamictp - dynamic-tp-jvmti-runtime - diff --git a/extension/extension-skywalking/src/main/java/org/dromara/dynamictp/extension/skywalking/init/SwInitializer.java b/extension/extension-skywalking/src/main/java/org/dromara/dynamictp/extension/skywalking/init/SwInitializer.java deleted file mode 100644 index ff83ffd95..000000000 --- a/extension/extension-skywalking/src/main/java/org/dromara/dynamictp/extension/skywalking/init/SwInitializer.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.dromara.dynamictp.extension.skywalking.init; - -import lombok.extern.slf4j.Slf4j; -import org.apache.commons.collections4.CollectionUtils; -import org.dromara.dynamictp.core.support.init.DtpInitializer; -import org.dromara.dynamictp.jvmti.JVMTI; - -import java.util.List; - -import static org.dromara.dynamictp.common.constant.DynamicTpConst.DTP_EXECUTE_ENHANCED; -import static org.dromara.dynamictp.common.constant.DynamicTpConst.FALSE_STR; - -/** - * SwInitializer related - * - * @author yanhom - * @since 1.1.6 - */ -@Slf4j -public class SwInitializer implements DtpInitializer { - - private static final String SW_AGENT_CLASS_LOADER = "org.apache.skywalking.apm.agent.core.plugin.loader.AgentClassLoader"; - - private static final String SW_RUNNABLE_WRAPPER = "org.apache.skywalking.apm.plugin.wrapper.SwRunnableWrapper"; - - private static final String SW_CALLABLE_WRAPPER = "org.apache.skywalking.apm.plugin.wrapper.SwCallableWrapper"; - - @Override - public String getName() { - return "SwInitializer"; - } - - @Override - public void init() { - try { - List classLoaders = JVMTI.getInstances(ClassLoader.class); - if (CollectionUtils.isEmpty(classLoaders)) { - return; - } - for (ClassLoader cl : classLoaders) { - if (!SW_AGENT_CLASS_LOADER.equals(cl.getClass().getName())) { - continue; - } - if (conditionOnClass(SW_RUNNABLE_WRAPPER, cl) || conditionOnClass(SW_CALLABLE_WRAPPER, cl)) { - System.setProperty(DTP_EXECUTE_ENHANCED, FALSE_STR); - log.warn("DynamicTp init, disable enhancement for the execute method " + - "in the presence of the skywalking threadpool plugin."); - return; - } - } - } catch (Throwable e) { - log.error("DynamicTp {} init failed", getName(), e); - } - } - - private boolean conditionOnClass(String className, ClassLoader classLoader) { - try { - Class.forName(className, false, classLoader); - return true; - } catch (ClassNotFoundException e) { - return false; - } - } -} diff --git a/extension/extension-skywalking/src/main/resources/META-INF/services/org.dromara.dynamictp.core.support.init.DtpInitializer b/extension/extension-skywalking/src/main/resources/META-INF/services/org.dromara.dynamictp.core.support.init.DtpInitializer deleted file mode 100644 index aa2e33bdc..000000000 --- a/extension/extension-skywalking/src/main/resources/META-INF/services/org.dromara.dynamictp.core.support.init.DtpInitializer +++ /dev/null @@ -1 +0,0 @@ -org.dromara.dynamictp.extension.skywalking.init.SwInitializer \ No newline at end of file diff --git a/extension/pom.xml b/extension/pom.xml index 0941b815a..a2d20349d 100644 --- a/extension/pom.xml +++ b/extension/pom.xml @@ -17,6 +17,7 @@ extension-notify-email extension-opentelemetry extension-notify-yunzhijia + extension-agent diff --git a/pom.xml b/pom.xml index 0e67e111e..10417deba 100644 --- a/pom.xml +++ b/pom.xml @@ -13,7 +13,7 @@ https://github.com/yanhom1314/dynamic-tp - 1.1.7 + 1.1.8-beta 8 8 diff --git a/starter/starter-adapter/starter-adapter-webserver/src/main/java/org/dromara/dynamictp/starter/adapter/webserver/undertow/EnhancedQueueExecutorProxy.java b/starter/starter-adapter/starter-adapter-webserver/src/main/java/org/dromara/dynamictp/starter/adapter/webserver/undertow/EnhancedQueueExecutorProxy.java index f34d27d70..b0dcf9faa 100644 --- a/starter/starter-adapter/starter-adapter-webserver/src/main/java/org/dromara/dynamictp/starter/adapter/webserver/undertow/EnhancedQueueExecutorProxy.java +++ b/starter/starter-adapter/starter-adapter-webserver/src/main/java/org/dromara/dynamictp/starter/adapter/webserver/undertow/EnhancedQueueExecutorProxy.java @@ -18,9 +18,12 @@ package org.dromara.dynamictp.starter.adapter.webserver.undertow; import org.dromara.dynamictp.core.aware.AwareManager; +import org.dromara.dynamictp.core.aware.TaskEnhanceAware; import org.dromara.dynamictp.core.support.task.runnable.EnhancedRunnable; +import org.dromara.dynamictp.core.support.task.wrapper.TaskWrapper; import org.jboss.threads.EnhancedQueueExecutor; +import java.util.List; import java.util.concurrent.RejectedExecutionException; /** @@ -30,7 +33,9 @@ * @since 1.1.4 **/ @SuppressWarnings("all") -public class EnhancedQueueExecutorProxy extends EnhancedQueueExecutor { +public class EnhancedQueueExecutorProxy extends EnhancedQueueExecutor implements TaskEnhanceAware { + + private List taskWrappers; public EnhancedQueueExecutorProxy(final Builder builder) { super(builder); @@ -49,19 +54,29 @@ public EnhancedQueueExecutorProxy(final EnhancedQueueExecutor executor) { @Override public void execute(Runnable runnable) { - EnhancedRunnable enhanceTask = EnhancedRunnable.of(runnable, this); - AwareManager.execute(this, enhanceTask); + Runnable enhancedTask = getEnhancedTask(EnhancedRunnable.of(runnable, this)); + AwareManager.execute(this, enhancedTask); try { - super.execute(enhanceTask); + super.execute(enhancedTask); } catch (Throwable e) { Throwable[] suppressedExceptions = e.getSuppressed(); for (Throwable t : suppressedExceptions) { if (t instanceof RejectedExecutionException) { - AwareManager.beforeReject(enhanceTask, this); + AwareManager.beforeReject(enhancedTask, this); return; } } throw e; } } + + @Override + public List getTaskWrappers() { + return this.taskWrappers; + } + + @Override + public void setTaskWrappers(List taskWrappers) { + this.taskWrappers = taskWrappers; + } } diff --git a/test/pom.xml b/test/pom.xml index af7a147e9..0423f3252 100644 --- a/test/pom.xml +++ b/test/pom.xml @@ -17,6 +17,7 @@ test-core test-logging test-configcenter + test-extension diff --git a/test/test-extension/pom.xml b/test/test-extension/pom.xml new file mode 100644 index 000000000..42d887aaf --- /dev/null +++ b/test/test-extension/pom.xml @@ -0,0 +1,37 @@ + + 4.0.0 + + org.dromara.dynamictp + dynamic-tp-all + ${revision} + ../../pom.xml + + + dynamic-tp-test-extension + jar + + test-extension + + + UTF-8 + + + + + junit + junit + test + + + + org.dromara.dynamictp + dynamic-tp-extension-agent + + + org.junit.jupiter + junit-jupiter-api + test + + + diff --git a/test/test-extension/src/test/java/org/dromara/dynamictp/agent/AgentAwareTest.java b/test/test-extension/src/test/java/org/dromara/dynamictp/agent/AgentAwareTest.java new file mode 100644 index 000000000..7525b188f --- /dev/null +++ b/test/test-extension/src/test/java/org/dromara/dynamictp/agent/AgentAwareTest.java @@ -0,0 +1,127 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.dromara.dynamictp.agent; + +import org.dromara.dynamictp.core.aware.AgentAware; +import org.dromara.dynamictp.core.support.task.runnable.DtpRunnable; +import org.junit.Test; +import org.junit.jupiter.api.Assertions; +import org.springframework.util.ReflectionUtils; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + +public class AgentAwareTest { + + @Test + public void testDirectOnlyOneDtpRunnable() throws InvocationTargetException, IllegalAccessException { + Method getDtpRunnableInstance = ReflectionUtils.findMethod(AgentAware.class, "getDtpRunnableInstance", Runnable.class); + Assertions.assertNotNull(getDtpRunnableInstance); + + getDtpRunnableInstance.setAccessible(true); + + Runnable runnable = () -> { + + }; + + + MyAgentWrapper myAgentWrapper = new MyAgentWrapper(runnable, new Object()); + Object result = getDtpRunnableInstance.invoke(new AgentAware(), myAgentWrapper); + Assertions.assertTrue(result == myAgentWrapper); + + DtpRunnable dtpRunnable = new DtpRunnable(runnable, runnable, "test"); + myAgentWrapper = new MyAgentWrapper(dtpRunnable, new Object()); + result = getDtpRunnableInstance.invoke(new AgentAware(), myAgentWrapper); + Assertions.assertNotNull(dtpRunnable == result); + } + + @Test + public void testDirectTwoRunnable() throws InvocationTargetException, IllegalAccessException { + Runnable runnable = () -> { + + }; + DtpRunnable dtpRunnable = new DtpRunnable(runnable, runnable, "test"); + MyAgentWrapperTwoRunnable myAgentWrapper = new MyAgentWrapperTwoRunnable(dtpRunnable, runnable, "test"); + + Method getDtpRunnableInstance = ReflectionUtils.findMethod(AgentAware.class, "getDtpRunnableInstance", Runnable.class); + Assertions.assertNotNull(getDtpRunnableInstance); + getDtpRunnableInstance.setAccessible(true); + + Object result = getDtpRunnableInstance.invoke(new AgentAware(), myAgentWrapper); + Assertions.assertTrue(result == dtpRunnable); + + myAgentWrapper = new MyAgentWrapperTwoRunnable(runnable, dtpRunnable, "test"); + result = getDtpRunnableInstance.invoke(new AgentAware(), myAgentWrapper); + Assertions.assertTrue(result == dtpRunnable); + } + + @Test + public void testNotDirectRunnable() throws InvocationTargetException, IllegalAccessException { + Runnable runnable = () -> { + + }; + DtpRunnable dtpRunnable = new DtpRunnable(runnable, runnable, "test"); + MyAgentWrapper myAgentWrapper = new MyAgentWrapper(dtpRunnable, new Object()); + + MyAgentTwoPathRunnableWrapper twoPathRunnableWrapper = new MyAgentTwoPathRunnableWrapper(myAgentWrapper, new Object()); + Method getDtpRunnableInstance = ReflectionUtils.findMethod(AgentAware.class, "getDtpRunnableInstance", Runnable.class); + Assertions.assertNotNull(getDtpRunnableInstance); + getDtpRunnableInstance.setAccessible(true); + + Object result = getDtpRunnableInstance.invoke(new AgentAware(), twoPathRunnableWrapper); + Assertions.assertTrue(result == dtpRunnable); + } + + @Test + public void testExtendRunnable() throws InvocationTargetException, IllegalAccessException { + Runnable runnable = () -> { + + }; + DtpRunnable dtpRunnable = new DtpRunnable(runnable, runnable, "test"); + MyAgentWrapper myAgentWrapper = new MyAgentWrapper(dtpRunnable, new Object()); + MyAgentWrapperChild myAgentWrapperChild = new MyAgentWrapperChild(myAgentWrapper, new Object()); + + Method getDtpRunnableInstance = ReflectionUtils.findMethod(AgentAware.class, "getDtpRunnableInstance", Runnable.class); + Assertions.assertNotNull(getDtpRunnableInstance); + getDtpRunnableInstance.setAccessible(true); + + Object result = getDtpRunnableInstance.invoke(new AgentAware(), myAgentWrapperChild); + Assertions.assertTrue(result == dtpRunnable); + } + + @Test + public void testDeepRunnable() throws InvocationTargetException, IllegalAccessException { + Runnable runnable = () -> { + + }; + DtpRunnable dtpRunnable = new DtpRunnable(runnable, runnable, "test"); + MyAgentWrapper myAgentWrapper = new MyAgentWrapper(runnable, new Object()); + MyAgentWrapper myAgentWrapperDtpRunnable = new MyAgentWrapper(dtpRunnable, new Object()); + MyAgentWrapperChild myAgentWrapperChild = new MyAgentWrapperChild(myAgentWrapperDtpRunnable, new Object()); + + MyAgentTwoPathRunnableChildWrapper myAgentTwoPathRunnableChildWrapper = new MyAgentTwoPathRunnableChildWrapper(myAgentWrapperChild, + myAgentWrapper, new Object()); + + Method getDtpRunnableInstance = ReflectionUtils.findMethod(AgentAware.class, "getDtpRunnableInstance", Runnable.class); + Assertions.assertNotNull(getDtpRunnableInstance); + getDtpRunnableInstance.setAccessible(true); + Object result = getDtpRunnableInstance.invoke(new AgentAware(), myAgentTwoPathRunnableChildWrapper); + Assertions.assertTrue(result == dtpRunnable); + } + +} diff --git a/test/test-extension/src/test/java/org/dromara/dynamictp/agent/MyAgentTwoPathRunnableChildWrapper.java b/test/test-extension/src/test/java/org/dromara/dynamictp/agent/MyAgentTwoPathRunnableChildWrapper.java new file mode 100644 index 000000000..f76d06bf7 --- /dev/null +++ b/test/test-extension/src/test/java/org/dromara/dynamictp/agent/MyAgentTwoPathRunnableChildWrapper.java @@ -0,0 +1,38 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.dromara.dynamictp.agent; + +public class MyAgentTwoPathRunnableChildWrapper implements Runnable { + + private MyAgentWrapperChild myAgentWrapperChild; + + private MyAgentWrapper myAgentWrapper; + + private Object busi; + + public MyAgentTwoPathRunnableChildWrapper(MyAgentWrapperChild myAgentWrapperChild, MyAgentWrapper myAgentWrapper, Object busi) { + this.myAgentWrapperChild = myAgentWrapperChild; + this.myAgentWrapper = myAgentWrapper; + this.busi = busi; + } + + @Override + public void run() { + System.out.println("MyAgentTwoPathRunnableChildWrapper"); + } +} diff --git a/test/test-extension/src/test/java/org/dromara/dynamictp/agent/MyAgentTwoPathRunnableWrapper.java b/test/test-extension/src/test/java/org/dromara/dynamictp/agent/MyAgentTwoPathRunnableWrapper.java new file mode 100644 index 000000000..0f3172661 --- /dev/null +++ b/test/test-extension/src/test/java/org/dromara/dynamictp/agent/MyAgentTwoPathRunnableWrapper.java @@ -0,0 +1,41 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.dromara.dynamictp.agent; + +public class MyAgentTwoPathRunnableWrapper implements Runnable { + + private final MyAgentWrapper myAgentWrapper; + + private final Object busiObj; + + public MyAgentTwoPathRunnableWrapper(MyAgentWrapper myAgentWrapper, Object busiObj) { + this.myAgentWrapper = myAgentWrapper; + this.busiObj = busiObj; + } + + + @Override + public void run() { + System.out.println("before"); + try { + myAgentWrapper.run(); + } finally { + System.out.println("finally"); + } + } +} diff --git a/test/test-extension/src/test/java/org/dromara/dynamictp/agent/MyAgentWrapper.java b/test/test-extension/src/test/java/org/dromara/dynamictp/agent/MyAgentWrapper.java new file mode 100644 index 000000000..0217e03bd --- /dev/null +++ b/test/test-extension/src/test/java/org/dromara/dynamictp/agent/MyAgentWrapper.java @@ -0,0 +1,40 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.dromara.dynamictp.agent; + +public class MyAgentWrapper implements Runnable { + + private Runnable runnable; + + private Object busiObj; + + public MyAgentWrapper(Runnable runnable, Object busiObj) { + this.runnable = runnable; + this.busiObj = busiObj; + } + + @Override + public void run() { + System.out.println("before"); + try { + runnable.run(); + } finally { + System.out.println("finally"); + } + } +} diff --git a/test/test-extension/src/test/java/org/dromara/dynamictp/agent/MyAgentWrapperChild.java b/test/test-extension/src/test/java/org/dromara/dynamictp/agent/MyAgentWrapperChild.java new file mode 100644 index 000000000..91117d315 --- /dev/null +++ b/test/test-extension/src/test/java/org/dromara/dynamictp/agent/MyAgentWrapperChild.java @@ -0,0 +1,29 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.dromara.dynamictp.agent; + +public class MyAgentWrapperChild extends MyAgentWrapper { + public MyAgentWrapperChild(MyAgentWrapper runnable, Object busiObj) { + super(runnable, busiObj); + } + + @Override + public void run() { + System.out.println("MyAgentWrapperChild"); + } +} diff --git a/test/test-extension/src/test/java/org/dromara/dynamictp/agent/MyAgentWrapperTwoRunnable.java b/test/test-extension/src/test/java/org/dromara/dynamictp/agent/MyAgentWrapperTwoRunnable.java new file mode 100644 index 000000000..c93c647dd --- /dev/null +++ b/test/test-extension/src/test/java/org/dromara/dynamictp/agent/MyAgentWrapperTwoRunnable.java @@ -0,0 +1,44 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.dromara.dynamictp.agent; + +public class MyAgentWrapperTwoRunnable implements Runnable { + + private Runnable r1; + + private Runnable r2; + + private Object busiObj; + + public MyAgentWrapperTwoRunnable(Runnable r1, Runnable r2, Object busiObj) { + this.r1 = r1; + this.r2 = r2; + this.busiObj = busiObj; + } + + @Override + public void run() { + System.out.println("before"); + try { + r1.run(); + r2.run(); + } finally { + System.out.println("after"); + } + } +}