diff --git a/skywalking-sdk-plugin/spring-plugin/src/main/java/com/ai/cloud/skywalking/plugin/spring/SpringTagNamespaceHandler.java b/skywalking-sdk-plugin/spring-plugin/src/main/java/com/ai/cloud/skywalking/plugin/spring/SpringTagNamespaceHandler.java new file mode 100644 index 000000000..b7529cc7e --- /dev/null +++ b/skywalking-sdk-plugin/spring-plugin/src/main/java/com/ai/cloud/skywalking/plugin/spring/SpringTagNamespaceHandler.java @@ -0,0 +1,11 @@ +package com.ai.cloud.skywalking.plugin.spring; + +import org.springframework.beans.factory.xml.NamespaceHandlerSupport; + +public class SpringTagNamespaceHandler extends NamespaceHandlerSupport { + @Override + public void init() { + registerBeanDefinitionParser("tracing-bean", new TracingBeanParser()); + registerBeanDefinitionParser("trace", new TraceParser()); + } +} diff --git a/skywalking-sdk-plugin/spring-plugin/src/main/java/com/ai/cloud/skywalking/plugin/spring/TestBeanFactoryPostProcessor.java b/skywalking-sdk-plugin/spring-plugin/src/main/java/com/ai/cloud/skywalking/plugin/spring/TestBeanFactoryPostProcessor.java deleted file mode 100644 index ba58fc440..000000000 --- a/skywalking-sdk-plugin/spring-plugin/src/main/java/com/ai/cloud/skywalking/plugin/spring/TestBeanFactoryPostProcessor.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.ai.cloud.skywalking.plugin.spring; - -import org.springframework.beans.BeansException; -import org.springframework.beans.factory.config.BeanPostProcessor; - -public class TestBeanFactoryPostProcessor implements BeanPostProcessor { - - - @Override - public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { - System.out.println(bean.getClass().getName()); - return bean; - } - - @Override - public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { - System.out.println(bean.getClass().getName()); - return bean; - } -} 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 d087861ed..5af414491 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 @@ -1,7 +1,8 @@ -package com.ai.cloud.skywalking.plugin.spring; +package com.ai.spring.plugin; import com.ai.cloud.skywalking.buriedpoint.LocalBuriedPointSender; import com.ai.cloud.skywalking.model.Identification; +import com.ai.cloud.skywalking.plugin.spring.TracingClassBean; import com.ai.cloud.skywalking.plugin.spring.util.ConcurrentHashSet; import javassist.*; import javassist.bytecode.AnnotationsAttribute; @@ -15,21 +16,14 @@ import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; -import java.util.ArrayList; -import java.util.List; import java.util.Set; import java.util.concurrent.ThreadLocalRandom; -import java.util.logging.Level; -import java.util.logging.Logger; public class TracingEnhanceProcessor implements DisposableBean, BeanPostProcessor, BeanFactoryPostProcessor, ApplicationContextAware { - private Logger logger = Logger.getLogger(TracingEnhanceProcessor.class.getName()); - private final Set beanSet = new ConcurrentHashSet(); private ApplicationContext applicationContext; - @Override public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { applicationContext.getBeansOfType(TracingClassBean.class); @@ -41,15 +35,38 @@ public class TracingEnhanceProcessor implements DisposableBean, BeanPostProcesso return bean; } + 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 && ".*".equals(pattern)) { + String newPattern = pattern.substring(0, pattern.lastIndexOf(".*")); + result = value.startsWith(newPattern); + } else { + if ("*".equals(pattern) && matchType != MatchType.PACKAGE) { + 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 { - boolean isMatch = false; + String packageName = bean.getClass().getPackage().getName(); + String className = bean.getClass().getSimpleName(); TracingClassBean matchClassBean = null; + boolean isMatch = false; for (TracingClassBean tracingClassBean : beanSet) { - //不符合符合规则 - //报名只支持精确匹配,类名支持*号模糊 - if (isPackageMatch(bean.getClass().getPackage().getName(), tracingClassBean.getPackageName()) - || isClassNameMatch(bean, tracingClassBean.getClassName())) { + if (checkMatch(packageName, tracingClassBean.getPackageName(), MatchType.PACKAGE) + || checkMatch(className, tracingClassBean.getClassName(), MatchType.CLASS)) { isMatch = true; matchClassBean = tracingClassBean; continue; @@ -64,104 +81,91 @@ public class TracingEnhanceProcessor implements DisposableBean, BeanPostProcesso ClassPool pool = ClassPool.getDefault(); CtClass ctSource = pool.get(bean.getClass().getName()); CtClass ctDestination = pool.makeClass(generateProxyClassName(bean), ctSource); - //拷贝所有的方法,所有的属性以及注解 - copy(ctSource, ctDestination); - - String methodPrefix = matchClassBean.getMethod(); - if (matchClassBean.getMethod().indexOf("*") != -1) { - methodPrefix = methodPrefix.substring(0, matchClassBean.getMethod().indexOf("*")); - } - - List methods = new ArrayList(); - for (CtMethod method : ctDestination.getDeclaredMethods()) { - if (methodPrefix.length() <= 0 || method.getName().startsWith(methodPrefix)) { - methods.add(method); + //拷贝所有的方法, + copyAllFields(ctSource, ctDestination); + // 拷贝所有的注解 + copyClassAnnotation(ctSource, ctDestination); + //拷贝所有的方法,并增强 + ConstPool cp = ctDestination.getClassFile().getConstPool(); + for (CtMethod m : ctSource.getDeclaredMethods()) { + CtMethod newm = CtNewMethod.copy(m, m.getName(), ctDestination, null); + copyMethodAnnotation(cp, m, newm); + // 是否符合规范,符合则增强 + if (checkMatch(m.getName(), matchClassBean.getMethod(), MatchType.METHOD)) { + enhanceMethod(bean, newm); } + ctDestination.addMethod(newm); } - for (CtMethod method : methods) { - enhanceMethod(bean, method); - } - - // 判断是否存在无参的构造函数,如果没有,则 - // 生成实例,构造函数 Class generateClass = ctDestination.toClass(); - Object newBean = generateClass.newInstance(); BeanUtils.copyProperties(bean, newBean); return newBean; } catch (NotFoundException e) { - logger.log(Level.ALL, "Class [" + beanName.getClass().getName() + "] cannot be found"); 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) { - e.printStackTrace(); + throw new IllegalStateException("Failed to instance class[" + beanName.getClass().getName() + "]", e); } catch (IllegalAccessException e) { - e.printStackTrace(); + throw new IllegalStateException("Failed to access class[" + beanName.getClass().getName() + "]", e); + } + } + + 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)); } - return bean; } private String generateProxyClassName(Object bean) { return bean.getClass().getName() + "$EnhanceBySWTracing$" + ThreadLocalRandom.current().nextInt(100); } - private void copy(CtClass ctSource, CtClass ctDestination) { - try { - // copy fields - ConstPool cp = ctDestination.getClassFile().getConstPool(); - for (CtField f : ctSource.getDeclaredFields()) { - CtClass fieldTypeClass = ClassPool.getDefault().get(f.getType().getName()); - //with annotations - AnnotationsAttribute invAnn = (AnnotationsAttribute) f.getFieldInfo().getAttribute( - AnnotationsAttribute.invisibleTag); - AnnotationsAttribute visAnn = (AnnotationsAttribute) f.getFieldInfo().getAttribute( - AnnotationsAttribute.visibleTag); - CtField ctField = new CtField(fieldTypeClass, f.getName(), ctDestination); - if (invAnn != null) { - ctField.getFieldInfo().addAttribute(invAnn.copy(cp, null)); - } - if (visAnn != null) { - ctField.getFieldInfo().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); + } + } - ctDestination.addField(ctField); - } - // copy methods - for (CtMethod m : ctSource.getDeclaredMethods()) { - //copy the method prefixing it with the source class name - CtMethod newm = CtNewMethod.copy(m, /*ctSource.getSimpleName() + "_" + */m.getName(), ctDestination, null); - // with annotations - 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 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); - ctDestination.addMethod(newm); - } + if (invAnn != null) { + ctDestinationField.getFieldInfo().addAttribute(invAnn.copy(cp, null)); + } + if (visAnn != null) { + ctDestinationField.getFieldInfo().addAttribute(visAnn.copy(cp, null)); + } + } - // copy annotation - 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)); - } - - } catch (Exception e) { - logger.log(Level.ALL, "Failed to generate proxy class "); - throw new IllegalStateException("Failed to generate proxy class"); + 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)); } }