diff --git a/discovery-agent-starter/src/main/java/com/nepxion/discovery/agent/constant/DiscoveryAgentConstant.java b/discovery-agent-starter/src/main/java/com/nepxion/discovery/agent/constant/DiscoveryAgentConstant.java
index 5f83d46..84c00ec 100644
--- a/discovery-agent-starter/src/main/java/com/nepxion/discovery/agent/constant/DiscoveryAgentConstant.java
+++ b/discovery-agent-starter/src/main/java/com/nepxion/discovery/agent/constant/DiscoveryAgentConstant.java
@@ -10,7 +10,7 @@
*/
public class DiscoveryAgentConstant {
- public static final String DISCOVERY_AGENT_VERSION = "1.1.0";
+ public static final String DISCOVERY_AGENT_VERSION = "1.3.0";
public static final String SPRING_APPLICATION_DISCOVERY_AGENT_VERSION = "spring.application.discovery.agent.version";
}
\ No newline at end of file
diff --git a/discovery-agent-starter/src/main/java/com/nepxion/discovery/agent/plugin/thread/ThreadConstant.java b/discovery-agent-starter/src/main/java/com/nepxion/discovery/agent/plugin/thread/ThreadConstant.java
index 93c3cd3..b8e6df7 100644
--- a/discovery-agent-starter/src/main/java/com/nepxion/discovery/agent/plugin/thread/ThreadConstant.java
+++ b/discovery-agent-starter/src/main/java/com/nepxion/discovery/agent/plugin/thread/ThreadConstant.java
@@ -17,7 +17,11 @@ public class ThreadConstant {
public static final String THREAD_SCAN_PACKAGES = "thread.scan.packages";
public static final String THREAD_REQUEST_DECORATOR_ENABLED = "thread.request.decorator.enabled";
public static final String RUNNABLE_CLASS_NAME = "java.lang.Runnable";
+ public static final String RUNNABLE_IMPL_METHOD_NAME = "run";
public static final String CALLABLE_CLASS_NAME = "java.util.concurrent.Callable";
+ public static final String CALLABLE_IMPL_METHOD_NAME = "call";
+ public static final String SUPPLIER_CLASS_NAME = "java.util.function.Supplier";
+ public static final String SUPPLIER_IMPL_METHOD_NAME = "get";
public static final String THREAD_SCAN_PACKAGES_DELIMITERS = ";";
public static final String CONSTRUCTOR_INTERCEPTOR = String.format("%s.before(this);\n", ThreadConstructorInterceptor.class.getName());
diff --git a/discovery-agent-starter/src/main/java/com/nepxion/discovery/agent/plugin/thread/ThreadPlugin.java b/discovery-agent-starter/src/main/java/com/nepxion/discovery/agent/plugin/thread/ThreadPlugin.java
index 4c33014..6d9de08 100644
--- a/discovery-agent-starter/src/main/java/com/nepxion/discovery/agent/plugin/thread/ThreadPlugin.java
+++ b/discovery-agent-starter/src/main/java/com/nepxion/discovery/agent/plugin/thread/ThreadPlugin.java
@@ -8,28 +8,16 @@
* @author zifeihan
* @version 1.0
*/
-
-import javassist.ClassPool;
-import javassist.CtClass;
-import javassist.CtConstructor;
-import javassist.CtField;
-import javassist.CtMethod;
-
-import java.lang.reflect.Method;
-import java.security.ProtectionDomain;
import java.util.HashSet;
import java.util.List;
import java.util.Properties;
-import com.nepxion.discovery.agent.async.AsyncContextAccessor;
-import com.nepxion.discovery.agent.callback.TransformCallback;
import com.nepxion.discovery.agent.callback.TransformTemplate;
import com.nepxion.discovery.agent.config.Config;
import com.nepxion.discovery.agent.logger.AgentLogger;
import com.nepxion.discovery.agent.matcher.MatcherFactory;
import com.nepxion.discovery.agent.matcher.MatcherOperator;
import com.nepxion.discovery.agent.plugin.Plugin;
-import com.nepxion.discovery.agent.util.ClassInfo;
import com.nepxion.discovery.agent.util.StringUtil;
public class ThreadPlugin extends Plugin {
@@ -61,112 +49,39 @@ public void install(TransformTemplate transformTemplate) {
RunnableTransformCallback runnableTransformCallback = new RunnableTransformCallback();
CallableTransformCallback callableTransformCallback = new CallableTransformCallback();
+ SupplierTransformCallback supplierTransformCallback = new SupplierTransformCallback();
for (String basePackage : scanPackages) {
MatcherOperator runnableInterfaceMatcherOperator = MatcherFactory.newPackageBasedMatcher(basePackage, ThreadConstant.RUNNABLE_CLASS_NAME);
MatcherOperator callableInterfaceMatcherOperator = MatcherFactory.newPackageBasedMatcher(basePackage, ThreadConstant.CALLABLE_CLASS_NAME);
+ MatcherOperator supplierInterfaceMatcherOperator = MatcherFactory.newPackageBasedMatcher(basePackage, ThreadConstant.SUPPLIER_CLASS_NAME);
transformTemplate.transform(runnableInterfaceMatcherOperator, runnableTransformCallback);
transformTemplate.transform(callableInterfaceMatcherOperator, callableTransformCallback);
+ transformTemplate.transform(supplierInterfaceMatcherOperator, supplierTransformCallback);
}
LOG.info(String.format("%s install successfully", this.getClass().getSimpleName()));
}
- public static class RunnableTransformCallback implements TransformCallback {
+ public static class RunnableTransformCallback extends ThreadTransformCallback {
@Override
- public byte[] doInTransform(ClassLoader classLoader, String className, Class> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) {
- try {
- ClassInfo classInfo = new ClassInfo(className, classfileBuffer, classLoader);
- CtClass ctClass = classInfo.getCtClass();
-
- addField(ctClass, AsyncContextAccessor.class);
-
- CtConstructor[] declaredConstructors = ctClass.getDeclaredConstructors();
- for (CtConstructor ctConstructor : declaredConstructors) {
- ctConstructor.insertAfter(ThreadConstant.CONSTRUCTOR_INTERCEPTOR);
- }
-
- CtMethod ctMethod = ctClass.getDeclaredMethod("run");
- if (null != ctMethod) {
- ctMethod.insertBefore(ThreadConstant.RUN_BEFORE_INTERCEPTOR);
- ctMethod.insertAfter(ThreadConstant.RUN_AFTER_INTERCEPTOR);
- }
-
- return ctClass.toBytecode();
- } catch (Exception e) {
- LOG.warn(String.format("Transform %s error,message:", className), e);
-
- return null;
- }
+ public String getImplMethodName() {
+ return ThreadConstant.RUNNABLE_IMPL_METHOD_NAME;
}
}
- public static void addField(CtClass ctClass, Class> clazz) {
- try {
- ClassPool aDefault = ClassPool.getDefault();
- CtClass makeInterface = aDefault.makeInterface(clazz.getName());
- ctClass.addInterface(makeInterface);
-
- Method[] methods = clazz.getDeclaredMethods();
- if (methods.length != 2) {
- throw new IllegalArgumentException("accessorType has to declare 2 methods. " + clazz.getName() + " has " + methods.length);
- }
-
- Method getter;
- Method setter;
-
- if (methods[0].getParameterTypes().length == 0) {
- getter = methods[0];
- setter = methods[1];
- } else {
- getter = methods[1];
- setter = methods[0];
- }
+ public static class CallableTransformCallback extends ThreadTransformCallback {
- Class> fieldType = getter.getReturnType();
- String fieldName = fieldType.getSimpleName().toLowerCase();
- String field = String.format("private %s %s;", fieldType.getName(), fieldName);
-
- CtField f1 = CtField.make(field, ctClass);
- ctClass.addField(f1);
-
- String getMethod = String.format("public %s %s(){return %s;}", fieldType.getName(), getter.getName(), fieldName);
- String setMethod = String.format("public void %s(%s %s){this.%s = %s;}", setter.getName(), fieldType.getName(), fieldName, fieldName, fieldName);
-
- CtMethod m1 = CtMethod.make(getMethod, ctClass);
- CtMethod m2 = CtMethod.make(setMethod, ctClass);
- ctClass.addMethod(m1);
- ctClass.addMethod(m2);
- } catch (Exception e) {
- LOG.warn(String.format("Add field %s error, message:", clazz.getName()), e);
+ @Override
+ public String getImplMethodName() {
+ return ThreadConstant.CALLABLE_IMPL_METHOD_NAME;
}
}
- public static class CallableTransformCallback implements TransformCallback {
- @Override
- public byte[] doInTransform(ClassLoader classLoader, String className, Class> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) {
- try {
- ClassInfo classInfo = new ClassInfo(className, classfileBuffer, classLoader);
- CtClass ctClass = classInfo.getCtClass();
-
- addField(ctClass, AsyncContextAccessor.class);
-
- CtConstructor[] declaredConstructors = ctClass.getDeclaredConstructors();
- for (CtConstructor ctConstructor : declaredConstructors) {
- ctConstructor.insertAfter(ThreadConstant.CONSTRUCTOR_INTERCEPTOR);
- }
-
- CtMethod ctMethod = ctClass.getDeclaredMethod("call");
- if (null != ctMethod) {
- ctMethod.insertBefore(ThreadConstant.RUN_BEFORE_INTERCEPTOR);
- ctMethod.insertAfter(ThreadConstant.RUN_AFTER_INTERCEPTOR);
- }
+ public static class SupplierTransformCallback extends ThreadTransformCallback {
- return ctClass.toBytecode();
- } catch (Exception e) {
- LOG.warn(String.format("Transform %s error, message:", className), e);
-
- return null;
- }
+ @Override
+ public String getImplMethodName() {
+ return ThreadConstant.SUPPLIER_IMPL_METHOD_NAME;
}
}
}
\ No newline at end of file
diff --git a/discovery-agent-starter/src/main/java/com/nepxion/discovery/agent/plugin/thread/ThreadTransformCallback.java b/discovery-agent-starter/src/main/java/com/nepxion/discovery/agent/plugin/thread/ThreadTransformCallback.java
new file mode 100644
index 0000000..a611960
--- /dev/null
+++ b/discovery-agent-starter/src/main/java/com/nepxion/discovery/agent/plugin/thread/ThreadTransformCallback.java
@@ -0,0 +1,99 @@
+package com.nepxion.discovery.agent.plugin.thread;
+
+/**
+ * Title: Nepxion Discovery
+ * Description: Nepxion Discovery
+ * Copyright: Copyright (c) 2017-2050
+ * Company: Nepxion
+ * @author zifeihan
+ * @version 1.0
+ */
+
+import javassist.ClassPool;
+import javassist.CtClass;
+import javassist.CtConstructor;
+import javassist.CtField;
+import javassist.CtMethod;
+
+import java.lang.reflect.Method;
+import java.security.ProtectionDomain;
+
+import com.nepxion.discovery.agent.async.AsyncContextAccessor;
+import com.nepxion.discovery.agent.callback.TransformCallback;
+import com.nepxion.discovery.agent.logger.AgentLogger;
+import com.nepxion.discovery.agent.util.ClassInfo;
+
+public abstract class ThreadTransformCallback implements TransformCallback {
+ private static final AgentLogger LOG = AgentLogger.getLogger(ThreadTransformCallback.class.getName());
+
+ @Override
+ public byte[] doInTransform(ClassLoader classLoader, String className, Class> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) {
+ try {
+ ClassInfo classInfo = new ClassInfo(className, classfileBuffer, classLoader);
+ CtClass ctClass = classInfo.getCtClass();
+
+ addField(ctClass, AsyncContextAccessor.class);
+
+ CtConstructor[] declaredConstructors = ctClass.getDeclaredConstructors();
+ for (CtConstructor ctConstructor : declaredConstructors) {
+ ctConstructor.insertAfter(ThreadConstant.CONSTRUCTOR_INTERCEPTOR);
+ }
+
+ String implMethodName = getImplMethodName();
+ CtMethod ctMethod = ctClass.getDeclaredMethod(implMethodName);
+ if (null != ctMethod) {
+ ctMethod.insertBefore(ThreadConstant.RUN_BEFORE_INTERCEPTOR);
+ ctMethod.insertAfter(ThreadConstant.RUN_AFTER_INTERCEPTOR);
+ }
+
+ return ctClass.toBytecode();
+ } catch (Exception e) {
+ LOG.warn(String.format("Transform %s error, message:", className), e);
+
+ return null;
+ }
+ }
+
+ public void addField(CtClass ctClass, Class> clazz) {
+ try {
+ ClassPool aDefault = ClassPool.getDefault();
+ CtClass makeInterface = aDefault.makeInterface(clazz.getName());
+ ctClass.addInterface(makeInterface);
+
+ Method[] methods = clazz.getDeclaredMethods();
+ if (methods.length != 2) {
+ throw new IllegalArgumentException("accessorType has to declare 2 methods. " + clazz.getName() + " has " + methods.length);
+ }
+
+ Method getter;
+ Method setter;
+
+ if (methods[0].getParameterTypes().length == 0) {
+ getter = methods[0];
+ setter = methods[1];
+ } else {
+ getter = methods[1];
+ setter = methods[0];
+ }
+
+ Class> fieldType = getter.getReturnType();
+ String fieldName = fieldType.getSimpleName().toLowerCase();
+ String field = String.format("private %s %s;", fieldType.getName(), fieldName);
+
+ CtField f1 = CtField.make(field, ctClass);
+ ctClass.addField(f1);
+
+ String getMethod = String.format("public %s %s(){return %s;}", fieldType.getName(), getter.getName(), fieldName);
+ String setMethod = String.format("public void %s(%s %s){this.%s = %s;}", setter.getName(), fieldType.getName(), fieldName, fieldName, fieldName);
+
+ CtMethod m1 = CtMethod.make(getMethod, ctClass);
+ CtMethod m2 = CtMethod.make(setMethod, ctClass);
+ ctClass.addMethod(m1);
+ ctClass.addMethod(m2);
+ } catch (Exception e) {
+ LOG.warn(String.format("Add field %s error, message:", clazz.getName()), e);
+ }
+ }
+
+ public abstract String getImplMethodName();
+}
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index fddef1b..bdca16d 100644
--- a/pom.xml
+++ b/pom.xml
@@ -6,7 +6,7 @@
Nepxion Discovery Agent
pom
4.0.0
- 1.1.0
+ 1.3.0
Nepxion Discovery Agent is a java agent to resolve loss of ThreadLocal in cross-thread scenario, such as Spring Async、Hystrix Thread、Runnable、Callable、Single Thread、Thread Pool、MDC
http://www.nepxion.com
@@ -18,7 +18,7 @@