diff --git a/skywalking-sdk-plugin/spring-plugin/pom.xml b/skywalking-sdk-plugin/spring-plugin/pom.xml
index 636685650..0a23bb992 100644
--- a/skywalking-sdk-plugin/spring-plugin/pom.xml
+++ b/skywalking-sdk-plugin/spring-plugin/pom.xml
@@ -34,36 +34,12 @@
3.8.1
compile
-
- org.springframework
- spring-beans
- 3.2.0.RELEASE
- compile
-
org.springframework
spring-context
3.2.0.RELEASE
compile
-
- org.springframework
- spring-web
- 3.2.0.RELEASE
- compile
-
-
- org.springframework
- spring-context
- 3.2.0.RELEASE
- test
-
-
- org.springframework
- spring-aop
- 3.2.0.RELEASE
- test
-
org.aspectj
aspectjweaver
@@ -76,21 +52,6 @@
${project.version}
test
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
junit
junit
diff --git a/skywalking-sdk-plugin/spring-plugin/src/main/java/com/ai/cloud/skywalking/plugin/spring/TracingEnhanceProcessor.java b/skywalking-sdk-plugin/spring-plugin/src/main/java/com/ai/cloud/skywalking/plugin/spring/TracingEnhanceProcessor.java
index e0c03c75e..febf2ca3c 100644
--- a/skywalking-sdk-plugin/spring-plugin/src/main/java/com/ai/cloud/skywalking/plugin/spring/TracingEnhanceProcessor.java
+++ b/skywalking-sdk-plugin/spring-plugin/src/main/java/com/ai/cloud/skywalking/plugin/spring/TracingEnhanceProcessor.java
@@ -3,12 +3,10 @@ package com.ai.cloud.skywalking.plugin.spring;
import com.ai.cloud.skywalking.buriedpoint.LocalBuriedPointSender;
import com.ai.cloud.skywalking.model.Identification;
import com.ai.cloud.skywalking.plugin.spring.util.ConcurrentHashSet;
-
import javassist.*;
+import javassist.Modifier;
import javassist.bytecode.AnnotationsAttribute;
import javassist.bytecode.ConstPool;
-
-import org.springframework.beans.BeanUtils;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
@@ -17,234 +15,261 @@ import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
+import java.lang.reflect.*;
import java.util.Set;
import java.util.concurrent.ThreadLocalRandom;
public class TracingEnhanceProcessor implements DisposableBean,
- BeanPostProcessor, BeanFactoryPostProcessor, ApplicationContextAware {
+ BeanPostProcessor, BeanFactoryPostProcessor, ApplicationContextAware {
- private final Set beanSet = new ConcurrentHashSet();
+ private final Set beanSet = new ConcurrentHashSet();
-
- @Override
- public void postProcessBeanFactory(
- ConfigurableListableBeanFactory beanFactory) throws BeansException {
- beanSet.addAll(applicationContext.getBeansOfType(TracingPattern.class)
- .values());
- }
+ @Override
+ public void postProcessBeanFactory(
+ ConfigurableListableBeanFactory beanFactory) throws BeansException {
+ beanSet.addAll(applicationContext.getBeansOfType(TracingPattern.class)
+ .values());
+ }
- @Override
- public Object postProcessBeforeInitialization(Object bean, String beanName)
- throws BeansException {
- return bean;
- }
+ @Override
+ public Object postProcessBeforeInitialization(Object bean, String beanName)
+ throws BeansException {
+ return bean;
+ }
- private ApplicationContext applicationContext;
+ private ApplicationContext applicationContext;
- @Override
- public void setApplicationContext(ApplicationContext applicationContext)
- throws BeansException {
- this.applicationContext = applicationContext;
- }
+ @Override
+ public void setApplicationContext(ApplicationContext applicationContext)
+ throws BeansException {
+ this.applicationContext = applicationContext;
+ }
- public enum MatchType {
- METHOD, PACKAGE, CLASS;
- }
+ public enum MatchType {
+ METHOD, PACKAGE, CLASS;
+ }
- private boolean checkMatch(String value, String pattern, MatchType matchType) {
- boolean result;
- if ("*".equals(pattern)) {
- return true;
- }
- if (matchType == MatchType.PACKAGE) {
- if (pattern.endsWith(".*")) {
- String newPattern = pattern.substring(0,
- pattern.lastIndexOf(".*"));
- result = value.startsWith(newPattern);
- } else {
- result = value.equals(pattern);
- }
- } else {
- if (pattern.endsWith("*")) {
- String newPattern = pattern.substring(0,
- pattern.lastIndexOf("*"));
- result = value.startsWith(newPattern);
- } else {
- result = value.equals(pattern);
- }
- }
- return result;
- }
+ private boolean checkMatch(String value, String pattern, MatchType matchType) {
+ boolean result;
+ if ("*".equals(pattern)) {
+ return true;
+ }
+ if (matchType == MatchType.PACKAGE) {
+ if (pattern.endsWith(".*")) {
+ String newPattern = pattern.substring(0,
+ pattern.lastIndexOf(".*"));
+ result = value.startsWith(newPattern);
+ } else {
+ result = value.equals(pattern);
+ }
+ } else {
+ if (pattern.endsWith("*")) {
+ String newPattern = pattern.substring(0,
+ pattern.lastIndexOf("*"));
+ result = value.startsWith(newPattern);
+ } else {
+ result = value.equals(pattern);
+ }
+ }
+ return result;
+ }
- @Override
- public Object postProcessAfterInitialization(Object bean, String beanName)
- throws BeansException {
- String packageName = bean.getClass().getPackage().getName();
- String className = bean.getClass().getSimpleName();
- TracingPattern matchClassBean = null;
- boolean isMatch = false;
- for (TracingPattern tracingPattern : beanSet) {
- if (checkMatch(packageName, tracingPattern.getPackageName(),
- MatchType.PACKAGE)
- && checkMatch(className, tracingPattern.getClassName(),
- MatchType.CLASS)) {
- isMatch = true;
- matchClassBean = tracingPattern;
- continue;
- }
- }
- if (!isMatch || matchClassBean == null) {
- return bean;
- }
+ @Override
+ public Object postProcessAfterInitialization(Object bean, String beanName)
+ throws BeansException {
+ String packageName;
+ if (bean.getClass().getPackage() == null) {
+ packageName = "";
+ } else {
+ packageName = bean.getClass().getPackage().getName();
+ }
+ String className = bean.getClass().getSimpleName();
+ TracingPattern matchClassBean = null;
+ boolean isMatch = false;
+ for (TracingPattern tracingPattern : beanSet) {
+ if (checkMatch(packageName, tracingPattern.getPackageName(),
+ MatchType.PACKAGE)
+ && checkMatch(className, tracingPattern.getClassName(),
+ MatchType.CLASS)) {
+ isMatch = true;
+ matchClassBean = tracingPattern;
+ continue;
+ }
+ }
+ if (!isMatch || matchClassBean == null) {
+ return bean;
+ }
- // 符合规范
- try {
- ClassPool pool = ClassPool.getDefault();
- CtClass ctSource = pool.get(bean.getClass().getName());
- CtClass ctDestination = pool.makeClass(
- generateProxyClassName(bean), ctSource);
- // 拷贝所有的方法,
- copyAllFields(ctSource, ctDestination);
- // 拷贝所有的注解
- copyClassAnnotation(ctSource, ctDestination);
- // 拷贝所有的方法,并增强
- ConstPool cp = ctDestination.getClassFile().getConstPool();
- for (CtMethod m : ctSource.getDeclaredMethods()) {
-
- if (m.getModifiers() == Modifier.PRIVATE){
- continue;
- }
-
- CtMethod newm = CtNewMethod.delegator(m, ctDestination);
- copyMethodAnnotation(cp, m, newm);
- // 是否符合规范,符合则增强
- if (checkMatch(m.getName(), matchClassBean.getMethod(),
- MatchType.METHOD)) {
- enhanceMethod(bean, newm);
- }
- ctDestination.addMethod(newm);
- }
+ // 符合规范
+ try {
+ ClassPool pool = ClassPool.getDefault();
+ pool.appendClassPath(new ClassClassPath(bean.getClass()));
+ CtClass ctSource = pool.get(bean.getClass().getName());
+ CtClass ctDestination = pool.makeClass(
+ generateProxyClassName(bean), ctSource);
+ for (CtClass interfaceCtClass : ctSource.getInterfaces()) {
+ ctDestination.addInterface(interfaceCtClass);
+ }
+ // 拷贝所有的注解
+ copyClassAnnotation(ctSource, ctDestination);
+ // 拷贝所有的方法,并增强
+ ConstPool cp = ctDestination.getClassFile().getConstPool();
+ for (CtMethod m : ctSource.getDeclaredMethods()) {
- Class> generateClass = ctDestination.toClass();
- Object newBean = generateClass.newInstance();
- BeanUtils.copyProperties(bean, newBean);
- return newBean;
- } catch (NotFoundException e) {
- throw new IllegalStateException("Class ["
- + beanName.getClass().getName() + "] cannot be found", e);
- } catch (CannotCompileException e) {
- throw new IllegalStateException("Class ["
- + beanName.getClass().getName() + "] cannot be compile", e);
- } catch (InstantiationException e) {
- throw new IllegalStateException("Failed to instance class["
- + beanName.getClass().getName() + "]", e);
- } catch (IllegalAccessException e) {
- throw new IllegalStateException("Failed to access class["
- + beanName.getClass().getName() + "]", e);
- }
- }
+ if (m.getModifiers() == Modifier.PRIVATE) {
+ continue;
+ }
-
+ CtMethod newm = CtNewMethod.delegator(m, ctDestination);
+ copyMethodAnnotation(cp, m, newm);
+ // 是否符合规范,符合则增强
+ if (checkMatch(m.getName(), matchClassBean.getMethod(),
+ MatchType.METHOD)) {
+ enhanceMethod(bean, newm);
+ }
+ ctDestination.addMethod(newm);
+ }
- private void copyMethodAnnotation(ConstPool cp, CtMethod m, CtMethod newm) {
- AnnotationsAttribute invAnn = (AnnotationsAttribute) m.getMethodInfo()
- .getAttribute(AnnotationsAttribute.invisibleTag);
- AnnotationsAttribute visAnn = (AnnotationsAttribute) m.getMethodInfo()
- .getAttribute(AnnotationsAttribute.visibleTag);
- if (invAnn != null) {
- newm.getMethodInfo().addAttribute(invAnn.copy(cp, null));
- }
- if (visAnn != null) {
- newm.getMethodInfo().addAttribute(visAnn.copy(cp, null));
- }
- }
+ Class> generateClass = ctDestination.toClass();
+ Object newBean = generateClass.newInstance();
+ Class currentClass = newBean.getClass().getSuperclass();
+ Class valueClass = bean.getClass();
+ Field tmpField = null;
+ while (true) {
+ if (currentClass.getName().equals(Object.class.getName())) {
+ break;
+ }
+ for (Field field : currentClass.getDeclaredFields()) {
+ if (Modifier.isStatic(field.getModifiers()) || Modifier.isFinal(field.getModifiers())){
+ continue;
+ }
+ field.setAccessible(true);
+ tmpField = valueClass.getDeclaredField(field.getName());
+ tmpField.setAccessible(true);
+ field.set(newBean, tmpField.get(bean));
+ }
+ currentClass = currentClass.getSuperclass();
+ valueClass = valueClass.getSuperclass();
+ }
+ return newBean;
+ } catch (NotFoundException e) {
+ throw new IllegalStateException("Class ["
+ + beanName.getClass().getName() + "] cannot be found", e);
+ } catch (CannotCompileException e) {
+ throw new IllegalStateException("Class ["
+ + beanName.getClass().getName() + "] cannot be compile", e);
+ } catch (InstantiationException e) {
+ throw new IllegalStateException("Failed to instance class["
+ + beanName.getClass().getName() + "]", e);
+ } catch (IllegalAccessException e) {
+ throw new IllegalStateException("Failed to access class["
+ + beanName.getClass().getName() + "]", e);
+ } catch (NoSuchFieldException e) {
+ throw new IllegalStateException("Failed to access class["
+ + beanName.getClass().getName() + "]", e);
+ }
+ }
- private String generateProxyClassName(Object bean) {
- return bean.getClass().getName() + "$EnhanceBySWTracing$"
- + ThreadLocalRandom.current().nextInt(100);
- }
+ private void copyMethodAnnotation(ConstPool cp, CtMethod m, CtMethod newm) {
+ AnnotationsAttribute invAnn = (AnnotationsAttribute) m.getMethodInfo()
+ .getAttribute(AnnotationsAttribute.invisibleTag);
+ AnnotationsAttribute visAnn = (AnnotationsAttribute) m.getMethodInfo()
+ .getAttribute(AnnotationsAttribute.visibleTag);
+ if (invAnn != null) {
+ newm.getMethodInfo().addAttribute(invAnn.copy(cp, null));
+ }
+ if (visAnn != null) {
+ newm.getMethodInfo().addAttribute(visAnn.copy(cp, null));
+ }
+ }
- private void copyAllFields(CtClass ctSource, CtClass ctDestination)
- throws CannotCompileException, NotFoundException {
- // copy fields
- ConstPool cp = ctDestination.getClassFile().getConstPool();
- for (CtField ctSourceField : ctSource.getDeclaredFields()) {
- CtClass fieldTypeClass = ClassPool.getDefault().get(
- ctSourceField.getType().getName());
- CtField ctField = new CtField(fieldTypeClass,
- ctSourceField.getName(), ctDestination);
- // with annotations
- copyAllFieldAnnotation(cp, ctSourceField, ctField);
- ctDestination.addField(ctField);
- }
- }
+ private String generateProxyClassName(Object bean) {
+ return bean.getClass().getName() + "$EnhanceBySWTracing$"
+ + ThreadLocalRandom.current().nextInt(100);
+ }
- private void copyAllFieldAnnotation(ConstPool cp, CtField ctSourceField,
- CtField ctDestinationField) throws CannotCompileException {
- AnnotationsAttribute invAnn = (AnnotationsAttribute) ctSourceField
- .getFieldInfo().getAttribute(AnnotationsAttribute.invisibleTag);
- AnnotationsAttribute visAnn = (AnnotationsAttribute) ctSourceField
- .getFieldInfo().getAttribute(AnnotationsAttribute.visibleTag);
+ private void copyAllFields(CtClass ctSource, CtClass ctDestination)
+ throws CannotCompileException, NotFoundException {
+ // copy fields
+ ConstPool cp = ctDestination.getClassFile().getConstPool();
+ for (CtField ctSourceField : ctSource.getDeclaredFields()) {
+ CtClass fieldTypeClass = ClassPool.getDefault().get(
+ ctSourceField.getType().getName());
+ CtField ctField = new CtField(fieldTypeClass,
+ ctSourceField.getName(), ctDestination);
+ // with annotations
+ copyAllFieldAnnotation(cp, ctSourceField, ctField);
+ ctDestination.addField(ctField);
+ }
+ }
- if (invAnn != null) {
- ctDestinationField.getFieldInfo().addAttribute(
- invAnn.copy(cp, null));
- }
- if (visAnn != null) {
- ctDestinationField.getFieldInfo().addAttribute(
- visAnn.copy(cp, null));
- }
- }
+ private void copyAllFieldAnnotation(ConstPool cp, CtField ctSourceField,
+ CtField ctDestinationField) throws CannotCompileException {
+ AnnotationsAttribute invAnn = (AnnotationsAttribute) ctSourceField
+ .getFieldInfo().getAttribute(AnnotationsAttribute.invisibleTag);
+ AnnotationsAttribute visAnn = (AnnotationsAttribute) ctSourceField
+ .getFieldInfo().getAttribute(AnnotationsAttribute.visibleTag);
- private void copyClassAnnotation(CtClass ctSource, CtClass ctDestination) {
- ConstPool cp = ctDestination.getClassFile().getConstPool();
- AnnotationsAttribute invAnn = (AnnotationsAttribute) ctSource
- .getClassFile().getAttribute(AnnotationsAttribute.invisibleTag);
- AnnotationsAttribute visAnn = (AnnotationsAttribute) ctSource
- .getClassFile().getAttribute(AnnotationsAttribute.visibleTag);
- if (invAnn != null) {
- ctDestination.getClassFile().addAttribute(invAnn.copy(cp, null));
- }
- if (visAnn != null) {
- ctDestination.getClassFile().addAttribute(visAnn.copy(cp, null));
- }
- }
+ if (invAnn != null) {
+ ctDestinationField.getFieldInfo().addAttribute(
+ invAnn.copy(cp, null));
+ }
+ if (visAnn != null) {
+ ctDestinationField.getFieldInfo().addAttribute(
+ visAnn.copy(cp, null));
+ }
+ }
- protected void enhanceMethod(Object bean, CtMethod method)
- throws CannotCompileException, NotFoundException {
- ClassPool cp = method.getDeclaringClass().getClassPool();
- method.addLocalVariable("___sender",
- cp.get(LocalBuriedPointSender.class.getName()));
- method.insertBefore("___sender = new "
- + LocalBuriedPointSender.class.getName()
- + "();\n___sender.beforeSend"
- + generateBeforeSendParameter(bean, method) + "\n");
- method.addCatch("new " + LocalBuriedPointSender.class.getName()
- + "().handleException(e);throw e;", ClassPool.getDefault()
- .getCtClass(Throwable.class.getName()), "e");
- method.insertAfter("new " + LocalBuriedPointSender.class.getName()
- + "().afterSend();", true);
- }
+ private void copyClassAnnotation(CtClass ctSource, CtClass ctDestination) {
+ ConstPool cp = ctDestination.getClassFile().getConstPool();
+ AnnotationsAttribute invAnn = (AnnotationsAttribute) ctSource
+ .getClassFile().getAttribute(AnnotationsAttribute.invisibleTag);
+ AnnotationsAttribute visAnn = (AnnotationsAttribute) ctSource
+ .getClassFile().getAttribute(AnnotationsAttribute.visibleTag);
+ if (invAnn != null) {
+ ctDestination.getClassFile().addAttribute(invAnn.copy(cp, null));
+ }
+ if (visAnn != null) {
+ ctDestination.getClassFile().addAttribute(visAnn.copy(cp, null));
+ }
+ }
- private String generateBeforeSendParameter(Object bean, CtMethod method)
- throws NotFoundException {
- StringBuilder builder = new StringBuilder("("
- + Identification.class.getName() + ".newBuilder().viewPoint(\""
- + bean.getClass().getName() + "." + method.getName());
- builder.append("(");
- for (CtClass param : method.getParameterTypes()) {
- builder.append(param.getSimpleName() + ",");
- }
- if (method.getParameterTypes().length > 0) {
- builder = builder.delete(builder.length() - 1, builder.length());
- }
- builder.append(")");
- builder.append("\").spanType('M').build());");
- return builder.toString();
- }
+ protected void enhanceMethod(Object bean, CtMethod method)
+ throws CannotCompileException, NotFoundException {
+ ClassPool cp = method.getDeclaringClass().getClassPool();
+ method.addLocalVariable("___sender",
+ cp.get(LocalBuriedPointSender.class.getName()));
+ method.insertBefore("___sender = new "
+ + LocalBuriedPointSender.class.getName()
+ + "();\n___sender.beforeSend"
+ + generateBeforeSendParameter(bean, method) + "\n");
+ method.addCatch("new " + LocalBuriedPointSender.class.getName()
+ + "().handleException(e);throw e;", ClassPool.getDefault()
+ .getCtClass(Throwable.class.getName()), "e");
+ method.insertAfter("new " + LocalBuriedPointSender.class.getName()
+ + "().afterSend();", true);
+ }
- @Override
- public void destroy() throws Exception {
+ private String generateBeforeSendParameter(Object bean, CtMethod method)
+ throws NotFoundException {
+ StringBuilder builder = new StringBuilder("("
+ + Identification.class.getName() + ".newBuilder().viewPoint(\""
+ + bean.getClass().getName() + "." + method.getName());
+ builder.append("(");
+ for (CtClass param : method.getParameterTypes()) {
+ builder.append(param.getSimpleName() + ",");
+ }
+ if (method.getParameterTypes().length > 0) {
+ builder = builder.delete(builder.length() - 1, builder.length());
+ }
+ builder.append(")");
+ builder.append("\").spanType(\"M\").build());");
+ return builder.toString();
+ }
+
+ @Override
+ public void destroy() throws Exception {
+
+ }
- }
}
diff --git a/skywalking-sdk-plugin/spring-plugin/src/test/java/com/ai/cloud/skywalking/plugin/spring/TestBean.java b/skywalking-sdk-plugin/spring-plugin/src/test/java/com/ai/cloud/skywalking/plugin/spring/TestBean.java
index a39702fd7..96511be85 100644
--- a/skywalking-sdk-plugin/spring-plugin/src/test/java/com/ai/cloud/skywalking/plugin/spring/TestBean.java
+++ b/skywalking-sdk-plugin/spring-plugin/src/test/java/com/ai/cloud/skywalking/plugin/spring/TestBean.java
@@ -3,15 +3,24 @@ package com.ai.cloud.skywalking.plugin.spring;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class TestBean {
+ private String value;
- public void testPrintln(String value){
+ public void testPrintln(String value) {
System.out.println(value);
}
- public static void main(String[] args){
+ public static void main(String[] args) throws IllegalAccessException {
ClassPathXmlApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("classpath*:springConfig-common.xml");
TestBean testBean = classPathXmlApplicationContext.getBean(TestBean.class);
testBean.testPrintln("Hello World");
}
-}
\ No newline at end of file
+
+ public String getValue() {
+ return value;
+ }
+
+ public void setValue(String value) {
+ this.value = value;
+ }
+}
diff --git a/skywalking-sdk-plugin/spring-plugin/src/test/resources/springConfig-common.xml b/skywalking-sdk-plugin/spring-plugin/src/test/resources/springConfig-common.xml
index 0d282ea61..56d9a7cfa 100644
--- a/skywalking-sdk-plugin/spring-plugin/src/test/resources/springConfig-common.xml
+++ b/skywalking-sdk-plugin/spring-plugin/src/test/resources/springConfig-common.xml
@@ -7,8 +7,10 @@
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://cloud.asiainfo.com/schema/skywalking
http://cloud.asiainfo.com/schema/skywalking/skywalking.xsd">
-
-
-
+
+
+
+
+
\ No newline at end of file