完善Spring插件功能

This commit is contained in:
zhangxin10 2015-12-21 07:56:28 +08:00
parent 736c04be67
commit 39fb666a09
27 changed files with 305 additions and 750 deletions

View File

@ -76,15 +76,25 @@
<version>${project.version}</version>
<scope>test</scope>
</dependency>
<!--<dependency>-->
<!--<groupId>org.springframework</groupId>-->
<!--<artifactId>spring-context</artifactId>-->
<!--<version>3.0.0.RELEASE</version>-->
<!--</dependency>-->
<!--<dependency>-->
<!--<groupId>org.springframework</groupId>-->
<!--<artifactId>spring-expression</artifactId>-->
<!--<version>3.0.0.RELEASE</version>-->
<!--</dependency>-->
<!--<dependency>-->
<!--<groupId>com.ai.cloud</groupId>-->
<!--<artifactId>skywalking-auth</artifactId>-->
<!--<version>1.0-SNAPSHOT</version>-->
<!--</dependency>-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>3.2.9.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>3.0.0.RELEASE</version>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
</dependencies>
</project>

View File

@ -5,7 +5,7 @@ import org.springframework.beans.factory.xml.NamespaceHandlerSupport;
public class SpringTagNamespaceHandler extends NamespaceHandlerSupport {
@Override
public void init() {
registerBeanDefinitionParser("tracing-bean", new TracingBeanParser());
registerBeanDefinitionParser("tracing-bean", new TracingPatternParser());
registerBeanDefinitionParser("trace", new TraceParser());
}
}

View File

@ -7,23 +7,19 @@ import org.springframework.beans.factory.xml.ParserContext;
import org.w3c.dom.Element;
public class TraceParser implements BeanDefinitionParser {
private final String TRACE_APPLICATION_BEAN_NAME = "TracingApplication";
@Override
public BeanDefinition parse(Element element, ParserContext parserContext) {
if (parserContext.getRegistry().containsBeanDefinition(TRACE_APPLICATION_BEAN_NAME)) {
// 只能存在一个
throw new IllegalStateException("Duplicate spring bean id ");
}
RootBeanDefinition rootBeanDefinition = new RootBeanDefinition();
rootBeanDefinition.setLazyInit(false);
rootBeanDefinition.setBeanClass(TracingEnhanceProcessor.class);
String id = null;
id = element.getAttribute("name");
int counter = 2;
while (parserContext.getRegistry().containsBeanDefinition(id)) {
id = id + (counter++);
}
if (id != null && id.length() > 0) {
if (parserContext.getRegistry().containsBeanDefinition(id)) {
throw new IllegalStateException("Duplicate spring bean id " + id);
}
parserContext.getRegistry().registerBeanDefinition(id, rootBeanDefinition);
}
parserContext.getRegistry().registerBeanDefinition(TRACE_APPLICATION_BEAN_NAME, rootBeanDefinition);
return rootBeanDefinition;
}
}

View File

@ -1,11 +0,0 @@
package com.ai.cloud.skywalking.plugin.spring;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Tracing {
}

View File

@ -1,56 +0,0 @@
package com.ai.cloud.skywalking.plugin.spring;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.RuntimeBeanReference;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.beans.factory.xml.BeanDefinitionParser;
import org.springframework.beans.factory.xml.ParserContext;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
public class TracingBeanParser implements BeanDefinitionParser {
@Override
public BeanDefinition parse(Element element, ParserContext parserContext) {
// 获取Method并处理
String methodPattern = element.getAttribute("method");
if (methodPattern == null || methodPattern.length() == 0) {
throw new IllegalStateException("Miss method pattern");
}
String packageName = element.getAttribute("package");
String className = element.getAttribute("class");
RootBeanDefinition beanDefinition = new RootBeanDefinition();
beanDefinition.setBeanClass(TracingClassBean.class);
String id = null;
id =element.getAttribute("name");
int counter = 2;
while(parserContext.getRegistry().containsBeanDefinition(id)) {
id = id +(counter++);
}
if (id != null &&id.length() > 0) {
if(parserContext.getRegistry().containsBeanDefinition(id)) {
throw new IllegalStateException("Duplicate spring bean id " + id);
}
parserContext.getRegistry().registerBeanDefinition(id,beanDefinition);
}
NamedNodeMap nnm =element.getAttributes();
for (int i = 0; i <nnm.getLength(); i++) {
Node node =nnm.item(i);
String key =node.getLocalName();
String value =node.getNodeValue();
if(key.equals("entity")) {
if(parserContext.getRegistry().containsBeanDefinition(value)) {
beanDefinition.getPropertyValues().add(key,parserContext.getRegistry().getBeanDefinition(value));
} else {
beanDefinition.getPropertyValues().add(key,new RuntimeBeanReference(value));
}
} else {
beanDefinition.getPropertyValues().add(key,value);
}
}
return beanDefinition;
}
}

View File

@ -1,18 +1,12 @@
package com.ai.cloud.skywalking.plugin.spring;
import java.util.Set;
import java.util.concurrent.ThreadLocalRandom;
import javassist.CannotCompileException;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtField;
import javassist.CtMethod;
import javassist.CtNewMethod;
import javassist.NotFoundException;
import com.ai.cloud.skywalking.buriedpoint.LocalBuriedPointSender;
import com.ai.cloud.skywalking.model.Identification;
import com.ai.cloud.skywalking.plugin.spring.util.ConcurrentHashSet;
import com.ai.cloud.skywalking.util.StringUtil;
import javassist.*;
import javassist.bytecode.AnnotationsAttribute;
import javassist.bytecode.ConstPool;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.DisposableBean;
@ -22,240 +16,211 @@ import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import com.ai.cloud.skywalking.buriedpoint.LocalBuriedPointSender;
import com.ai.cloud.skywalking.model.Identification;
import com.ai.cloud.skywalking.plugin.spring.util.ConcurrentHashSet;
import java.util.Set;
import java.util.concurrent.ThreadLocalRandom;
public class TracingEnhanceProcessor implements DisposableBean,
BeanPostProcessor, BeanFactoryPostProcessor, ApplicationContextAware {
public class TracingEnhanceProcessor implements DisposableBean, BeanPostProcessor, BeanFactoryPostProcessor, ApplicationContextAware {
private final Set<TracingClassBean> beanSet = new ConcurrentHashSet<TracingClassBean>();
private ApplicationContext applicationContext;
private final Set<TracingPattern> beanSet = new ConcurrentHashSet<TracingPattern>();
@Override
public void postProcessBeanFactory(
ConfigurableListableBeanFactory beanFactory) throws BeansException {
applicationContext.getBeansOfType(TracingClassBean.class);
}
@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 enum MatchType {
METHOD, PACKAGE, CLASS;
}
private ApplicationContext applicationContext;
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 void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName)
throws BeansException {
String packageName = bean.getClass().getPackage().getName();
String className = bean.getClass().getSimpleName();
TracingClassBean matchClassBean = null;
boolean isMatch = false;
for (TracingClassBean tracingClassBean : beanSet) {
if (checkMatch(packageName, tracingClassBean.getPackageName(),
MatchType.PACKAGE)
|| checkMatch(className, tracingClassBean.getClassName(),
MatchType.CLASS)) {
isMatch = true;
matchClassBean = tracingClassBean;
continue;
}
}
if (!isMatch || matchClassBean == null) {
return bean;
}
public enum MatchType {
METHOD, PACKAGE, CLASS;
}
// 符合规范
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()) {
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);
}
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;
}
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);
}
}
@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;
}
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));
}
}
//符合规范
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()) {
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);
}
private String generateProxyClassName(Object bean) {
return bean.getClass().getName() + "$EnhanceBySWTracing$"
+ ThreadLocalRandom.current().nextInt(100);
}
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);
}
}
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 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 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 String generateProxyClassName(Object bean) {
return bean.getClass().getName() + "$EnhanceBySWTracing$" + ThreadLocalRandom.current().nextInt(100);
}
if (invAnn != null) {
ctDestinationField.getFieldInfo().addAttribute(
invAnn.copy(cp, null));
}
if (visAnn != null) {
ctDestinationField.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);
}
}
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 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);
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()
+ "();___sender.beforeSend"
+ generateBeforeSendParameter(bean, method));
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);
}
if (invAnn != null) {
ctDestinationField.getFieldInfo().addAttribute(invAnn.copy(cp, null));
}
if (visAnn != null) {
ctDestinationField.getFieldInfo().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();
}
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 boolean isClassNameMatch(Object bean, String tracingClassBean) {
//
String classNamePrefix = tracingClassBean;
if (tracingClassBean.endsWith("*")) {
classNamePrefix = tracingClassBean.substring(0,
tracingClassBean.indexOf('*'));
}
return bean.getClass().getSimpleName().startsWith(classNamePrefix);
}
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() + "();___sender.beforeSend"
+ generateBeforeSendParameter(bean, method));
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 boolean isPackageMatch(Object bean, String packageName) {
return bean.getClass().getPackage().equals(packageName);
}
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 setApplicationContext(ApplicationContext applicationContext)
throws BeansException {
this.applicationContext = applicationContext;
}
@Override
public void destroy() throws Exception {
private boolean isClassNameMatch(Object bean, String tracingClassBean) {
//
String classNamePrefix = tracingClassBean;
if (tracingClassBean.endsWith("*")) {
classNamePrefix = tracingClassBean.substring(0, tracingClassBean.indexOf('*'));
}
return bean.getClass().getSimpleName().startsWith(classNamePrefix);
}
}
private boolean isPackageMatch(Object bean, String packageName) {
return bean.getClass().getPackage().equals(packageName);
}
@Override
public void destroy() throws Exception {
}
}

View File

@ -1,6 +1,6 @@
package com.ai.cloud.skywalking.plugin.spring;
public class TracingClassBean {
public class TracingPattern {
private String packageName = "";
private String className = "";
private String method = "";

View File

@ -0,0 +1,54 @@
package com.ai.cloud.skywalking.plugin.spring;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.RuntimeBeanReference;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.beans.factory.xml.BeanDefinitionParser;
import org.springframework.beans.factory.xml.ParserContext;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
public class TracingPatternParser implements BeanDefinitionParser {
@Override
public BeanDefinition parse(Element element, ParserContext parserContext) {
// 获取Method并处理
String methodPattern = element.getAttribute("method");
if (methodPattern == null || methodPattern.length() == 0) {
throw new IllegalStateException("Miss method pattern");
}
RootBeanDefinition beanDefinition = new RootBeanDefinition();
beanDefinition.setBeanClass(TracingPattern.class);
String id = element.getAttribute("id");
if (id == null || id.length() == 0) {
id = TracingPattern.class.getName();
int counter = 2;
while (parserContext.getRegistry().containsBeanDefinition(id)) {
id = id + (counter++);
}
}
if (id != null && id.length() > 0) {
if (parserContext.getRegistry().containsBeanDefinition(id)) {
throw new IllegalStateException("Duplicate spring bean id " + id);
}
parserContext.getRegistry().registerBeanDefinition(id, beanDefinition);
}
NamedNodeMap nnm = element.getAttributes();
for (int i = 0; i < nnm.getLength(); i++) {
Node node = nnm.item(i);
String key = node.getLocalName();
String value = node.getNodeValue();
if (key.equals("entity")) {
if (parserContext.getRegistry().containsBeanDefinition(value)) {
beanDefinition.getPropertyValues().add(key, parserContext.getRegistry().getBeanDefinition(value));
} else {
beanDefinition.getPropertyValues().add(key, new RuntimeBeanReference(value));
}
} else {
beanDefinition.getPropertyValues().add(key, value);
}
}
return beanDefinition;
}
}

View File

@ -7,20 +7,16 @@
<xsd:element name="tracing-bean">
<xsd:complexType>
<xsd:attribute name="method" type="xsd:string" use="required"/>
<xsd:attribute name="method" type="xsd:string" use="optional" default="*"/>
<xsd:attribute name="packageName" type="xsd:string" use="required"/>
<xsd:attribute name="className" type="xsd:string" use="optional" default="*"/>
<xsd:attribute name="className" type="xsd:string" use="required"/>
</xsd:complexType>
</xsd:element>
<xsd:element name="trace">
<xsd:complexType>
<xsd:attribute name="turnOn" use="optional" default="true" type="xsd:boolean"/>
</xsd:complexType>
</xsd:element>
<!--<xsd:simpleType name="packageType">-->
<!--<xsd:restriction base="xsd:string">-->
<!--<xsd:whiteSpace value="replace"/>-->
<!--<xsd:pattern value="[a-z][a-z0-9]*([.][a-z][a-z0-9]*)+"/>-->
<!--</xsd:restriction>-->
<!--</xsd:simpleType>-->
</xsd:schema>

View File

@ -1,11 +0,0 @@
package com.ai.cloud.skywalking.plugin.spring.aspect;
public class AspectBean {
public void before() {
System.out.println("before aspect");
}
public void after() {
System.out.println("after aspect");
}
}

View File

@ -1,13 +0,0 @@
package com.ai.cloud.skywalking.plugin.spring.aspect;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class TestAspect {
public static void main(String[] args) {
ClassPathXmlApplicationContext classPathXmlApplicationContext =
new ClassPathXmlApplicationContext("classpath*:springConfig-aspect.xml");
TracingAspectBean testBuriedPointBean = classPathXmlApplicationContext.getBean(TracingAspectBean.class);
testBuriedPointBean.doBusiness();
}
}

View File

@ -1,12 +0,0 @@
package com.ai.cloud.skywalking.plugin.spring.aspect;
import com.ai.cloud.skywalking.plugin.spring.Tracing;
public class TracingAspectBean {
@Tracing
public String doBusiness() {
System.out.println("do business");
return "Hello World";
}
}

View File

@ -1,44 +0,0 @@
package com.ai.cloud.skywalking.plugin.spring.common;
import com.ai.cloud.skywalking.plugin.spring.Tracing;
import java.util.concurrent.ThreadLocalRandom;
public class CallChainA {
private CallChainB callChainB;
private CallChainD callChainD;
private CallChainF callChainF;
@Tracing
public void doBusiness() throws InterruptedException {
Thread.sleep(ThreadLocalRandom.current().nextInt(10));
callChainB.doBusiness();
callChainD.doBusiness();
callChainF.doBusiness();
Thread.sleep(ThreadLocalRandom.current().nextInt(10));
}
public CallChainB getCallChainB() {
return callChainB;
}
public void setCallChainB(CallChainB callChainB) {
this.callChainB = callChainB;
}
public CallChainD getCallChainD() {
return callChainD;
}
public void setCallChainD(CallChainD callChainD) {
this.callChainD = callChainD;
}
public CallChainF getCallChainF() {
return callChainF;
}
public void setCallChainF(CallChainF callChainF) {
this.callChainF = callChainF;
}
}

View File

@ -1,25 +0,0 @@
package com.ai.cloud.skywalking.plugin.spring.common;
import com.ai.cloud.skywalking.plugin.spring.Tracing;
import java.util.concurrent.ThreadLocalRandom;
public class CallChainB {
private CallChainC callChainC;
@Tracing
public void doBusiness() throws InterruptedException {
Thread.sleep(ThreadLocalRandom.current().nextInt(10));
callChainC.doBusiness();
Thread.sleep(ThreadLocalRandom.current().nextInt(10));
}
public CallChainC getCallChainC() {
return callChainC;
}
public void setCallChainC(CallChainC callChainC) {
this.callChainC = callChainC;
}
}

View File

@ -1,25 +0,0 @@
package com.ai.cloud.skywalking.plugin.spring.common;
import com.ai.cloud.skywalking.plugin.spring.Tracing;
import java.util.concurrent.ThreadLocalRandom;
public class CallChainC {
private CallChainE callChainE;
@Tracing
public void doBusiness() throws InterruptedException {
Thread.sleep(ThreadLocalRandom.current().nextInt(10));
callChainE.doBusiness();
Thread.sleep(ThreadLocalRandom.current().nextInt(10));
}
public CallChainE getCallChainE() {
return callChainE;
}
public void setCallChainE(CallChainE callChainE) {
this.callChainE = callChainE;
}
}

View File

@ -1,15 +0,0 @@
package com.ai.cloud.skywalking.plugin.spring.common;
import com.ai.cloud.skywalking.plugin.spring.Tracing;
import java.util.concurrent.ThreadLocalRandom;
public class CallChainD {
@Tracing
public void doBusiness() throws InterruptedException {
Thread.sleep(ThreadLocalRandom.current().nextInt(10));
//System.out.println("three");
}
}

View File

@ -1,27 +0,0 @@
package com.ai.cloud.skywalking.plugin.spring.common;
import com.ai.cloud.skywalking.api.BusinessKeyAppender;
import com.ai.cloud.skywalking.plugin.spring.Tracing;
import java.util.concurrent.ThreadLocalRandom;
public class CallChainE {
private CallChainG callChainG;
@Tracing
public void doBusiness() throws InterruptedException {
Thread.sleep(ThreadLocalRandom.current().nextInt(10));
BusinessKeyAppender.setBusinessKey2Trace("key-value");
callChainG.doBusiness();
Thread.sleep(ThreadLocalRandom.current().nextInt(10));
}
public CallChainG getCallChainG() {
return callChainG;
}
public void setCallChainG(CallChainG callChainG) {
this.callChainG = callChainG;
}
}

View File

@ -1,14 +0,0 @@
package com.ai.cloud.skywalking.plugin.spring.common;
import com.ai.cloud.skywalking.plugin.spring.Tracing;
import java.util.concurrent.ThreadLocalRandom;
public class CallChainF {
@Tracing
public void doBusiness() throws InterruptedException {
Thread.sleep(ThreadLocalRandom.current().nextInt(10));
//System.out.println("me too");
}
}

View File

@ -1,28 +0,0 @@
package com.ai.cloud.skywalking.plugin.spring.common;
import com.ai.cloud.skywalking.api.BusinessKeyAppender;
import com.ai.cloud.skywalking.plugin.spring.Tracing;
import java.util.concurrent.ThreadLocalRandom;
public class CallChainG {
private CallChainH callChainH;
@Tracing
public void doBusiness() throws InterruptedException {
Thread.sleep(ThreadLocalRandom.current().nextInt(10));
BusinessKeyAppender.setBusinessKey2Trace("key-value");
callChainH.doBusiness();
Thread.sleep(ThreadLocalRandom.current().nextInt(10));
}
public CallChainH getCallChainH() {
return callChainH;
}
public void setCallChainH(CallChainH callChainH) {
this.callChainH = callChainH;
}
}

View File

@ -1,28 +0,0 @@
package com.ai.cloud.skywalking.plugin.spring.common;
import com.ai.cloud.skywalking.api.BusinessKeyAppender;
import com.ai.cloud.skywalking.plugin.spring.Tracing;
import java.util.concurrent.ThreadLocalRandom;
public class CallChainH {
private CallChainI callChainI;
@Tracing
public void doBusiness() throws InterruptedException {
Thread.sleep(ThreadLocalRandom.current().nextInt(10));
BusinessKeyAppender.setBusinessKey2Trace("key-value");
callChainI.doBusiness();
Thread.sleep(ThreadLocalRandom.current().nextInt(10));
}
public CallChainI getCallChainI() {
return callChainI;
}
public void setCallChainI(CallChainI callChainI) {
this.callChainI = callChainI;
}
}

View File

@ -1,27 +0,0 @@
package com.ai.cloud.skywalking.plugin.spring.common;
import com.ai.cloud.skywalking.api.BusinessKeyAppender;
import com.ai.cloud.skywalking.plugin.spring.Tracing;
import java.util.concurrent.ThreadLocalRandom;
public class CallChainI {
private CallChainJ callChainJ;
@Tracing
public void doBusiness() throws InterruptedException {
Thread.sleep(ThreadLocalRandom.current().nextInt(10));
BusinessKeyAppender.setBusinessKey2Trace("key-value");
callChainJ.doBusiness();
Thread.sleep(ThreadLocalRandom.current().nextInt(10));
}
public CallChainJ getCallChainJ() {
return callChainJ;
}
public void setCallChainJ(CallChainJ callChainJ) {
this.callChainJ = callChainJ;
}
}

View File

@ -1,26 +0,0 @@
package com.ai.cloud.skywalking.plugin.spring.common;
import com.ai.cloud.skywalking.api.BusinessKeyAppender;
import com.ai.cloud.skywalking.plugin.spring.Tracing;
import java.util.concurrent.ThreadLocalRandom;
public class CallChainJ {
private CallChainK callChainK;
@Tracing
public void doBusiness() throws InterruptedException {
Thread.sleep(ThreadLocalRandom.current().nextInt(10));
BusinessKeyAppender.setBusinessKey2Trace("key-value");
callChainK.doBusiness();
Thread.sleep(ThreadLocalRandom.current().nextInt(10));
}
public CallChainK getCallChainK() {
return callChainK;
}
public void setCallChainK(CallChainK callChainK) {
this.callChainK = callChainK;
}
}

View File

@ -1,15 +0,0 @@
package com.ai.cloud.skywalking.plugin.spring.common;
import com.ai.cloud.skywalking.api.BusinessKeyAppender;
import com.ai.cloud.skywalking.plugin.spring.Tracing;
import java.util.concurrent.ThreadLocalRandom;
public class CallChainK {
@Tracing
public void doBusiness() throws InterruptedException {
Thread.sleep(ThreadLocalRandom.current().nextInt(10));
BusinessKeyAppender.setBusinessKey2Trace("key-value");
Thread.sleep(ThreadLocalRandom.current().nextInt(10));
}
}

View File

@ -1,60 +0,0 @@
package com.ai.cloud.skywalking.plugin.spring.common;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicInteger;
public class TestBuriedPoint extends Thread {
private static final int MAX_THREAD_SIZE = 1;
private CallChainA callChainA;
AtomicInteger atomicInteger = new AtomicInteger();
public TestBuriedPoint(CallChainA callChainA) {
this.callChainA = callChainA;
}
private Timer timer = new Timer(Thread.currentThread().getName());
public TestBuriedPoint() {
timer.schedule(new TimerTask() {
@Override
public void run() {
System.out.println(atomicInteger.get());
}
}, 1000);
}
@Override
public void run() {
for (int i = 0 ; i < 1; i++) {
try {
Thread.sleep(2L);
} catch (InterruptedException e) {
e.printStackTrace();
}
try {
callChainA.doBusiness();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "\t" + atomicInteger.incrementAndGet());
}
}
public static void main(String[] args) throws InterruptedException {
ClassPathXmlApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("classpath*:springConfig-common.xml");
CallChainA callChainA = classPathXmlApplicationContext.getBean(CallChainA.class);
CountDownLatch countDownLatch = new CountDownLatch(10);
for (int i = 0; i < MAX_THREAD_SIZE; i++) {
new TestBuriedPoint(callChainA).start();
}
countDownLatch.await();
}
}

View File

@ -0,0 +1,19 @@
package com.ai.cloud.skywalking.plugin.spring.test;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class AppTest01 {
public void testPrintln(String value){
System.out.println(value);
}
@Test
public void testBean(){
ClassPathXmlApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("classpath*:springConfig-common.xml");
AppTest01 appTest01 = classPathXmlApplicationContext.getBean(AppTest01.class);
appTest01.testPrintln("Hello World");
}
}

View File

@ -1,24 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">
<bean id="postProcess1"
class="com.ai.cloud.skywalking.plugin.spring.TracingEnhanceProcessor">
</bean>
<bean id="aspectBean" class="com.ai.cloud.skywalking.plugin.spring.aspect.AspectBean"/>
<bean id="testBuriedPointAspect" class="com.ai.cloud.skywalking.plugin.spring.aspect.TracingAspectBean"/>
<aop:config>
<aop:aspect ref="aspectBean">
<aop:pointcut id="testPointCut"
expression="execution(* com.ai.cloud.skywalking.plugin.spring.aspect..*(..))"/>
<aop:before method="before" pointcut-ref="testPointCut"/>
<aop:after method="after" pointcut-ref="testPointCut"/>
</aop:aspect>
</aop:config>
</beans>

View File

@ -2,40 +2,16 @@
<beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:skywalking="http://cloud.asiainfo.com/schema/skywalking"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
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">
<bean id="postProcess1"
class="com.ai.cloud.skywalking.plugin.spring.TracingEnhanceProcessor">
</bean>
<bean id="callChainK" class="com.ai.cloud.skywalking.plugin.spring.common.CallChainK"/>
<bean id="callChainJ" class="com.ai.cloud.skywalking.plugin.spring.common.CallChainJ">
<property name="callChainK" ref="callChainK"/>
</bean>
<bean id="callChainI" class="com.ai.cloud.skywalking.plugin.spring.common.CallChainI">
<property name="callChainJ" ref="callChainJ"/>
</bean>
<bean id="callChainH" class="com.ai.cloud.skywalking.plugin.spring.common.CallChainH">
<property name="callChainI" ref="callChainI"/>
</bean>
<skywalking:trace turnOn="true"/>
<skywalking:tracing-bean className="AppTest01" method="testPrintln*" packageName="*"/>
<bean id="testBean" class="com.ai.cloud.skywalking.plugin.spring.test.AppTest01"/>
<bean id="callChainG" class="com.ai.cloud.skywalking.plugin.spring.common.CallChainG">
<property name="callChainH" ref="callChainH"/>
</bean>
<bean id="callChainE" class="com.ai.cloud.skywalking.plugin.spring.common.CallChainE">
<property name="callChainG" ref="callChainG"/>
</bean>
<bean id="callChainF" class="com.ai.cloud.skywalking.plugin.spring.common.CallChainF"/>
<bean id="callChainC" class="com.ai.cloud.skywalking.plugin.spring.common.CallChainC">
<property name="callChainE" ref="callChainE"/>
</bean>
<bean id="callChainD" class="com.ai.cloud.skywalking.plugin.spring.common.CallChainD"/>
<bean id="callChainB" class="com.ai.cloud.skywalking.plugin.spring.common.CallChainB">
<property name="callChainC" ref="callChainC"/>
</bean>
<bean id="callChainA" class="com.ai.cloud.skywalking.plugin.spring.common.CallChainA">
<property name="callChainB" ref="callChainB"/>
<property name="callChainD" ref="callChainD"/>
<property name="callChainF" ref="callChainF"/>
</bean>
</beans>