提交 16aec017 编写于 作者: Z zhangxin10

完成Spring插件以及插件的测试

上级 2c050c05
......@@ -97,4 +97,26 @@
<version>4.12</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.6</source>
<target>1.6</target>
<encoding>${project.build.sourceEncoding}</encoding>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>2.4.3</version>
<configuration>
<encoding>${project.build.sourceEncoding}</encoding>
</configuration>
</plugin>
</plugins>
</build>
</project>
......@@ -5,7 +5,6 @@ import org.springframework.beans.factory.xml.NamespaceHandlerSupport;
public class SpringTagNamespaceHandler extends NamespaceHandlerSupport {
@Override
public void init() {
registerBeanDefinitionParser("tracing-bean", new TracingPatternParser());
registerBeanDefinitionParser("trace", new TraceParser());
registerBeanDefinitionParser("trace", new TracingPatternParser());
}
}
package com.ai.cloud.skywalking.plugin.spring;
import org.springframework.beans.factory.config.BeanDefinition;
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;
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 ");
}
boolean turnOn = Boolean.parseBoolean(element.getAttribute("turnOn"));
RootBeanDefinition rootBeanDefinition = new RootBeanDefinition();
rootBeanDefinition.setLazyInit(false);
rootBeanDefinition.setBeanClass(TracingEnhanceProcessor.class);
rootBeanDefinition.getPropertyValues().addPropertyValue("turnOn", turnOn);
parserContext.getRegistry().registerBeanDefinition(TRACE_APPLICATION_BEAN_NAME, rootBeanDefinition);
return rootBeanDefinition;
}
}
......@@ -3,10 +3,11 @@ 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 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;
......@@ -19,222 +20,226 @@ import org.springframework.context.ApplicationContextAware;
import java.util.Set;
import java.util.concurrent.ThreadLocalRandom;
public class TracingEnhanceProcessor implements DisposableBean, BeanPostProcessor, BeanFactoryPostProcessor, ApplicationContextAware {
private final Set<TracingPattern> beanSet = new ConcurrentHashSet<TracingPattern>();
private boolean turnOn;
public boolean isTurnOn() {
return turnOn;
}
public void setTurnOn(boolean turnOn) {
this.turnOn = turnOn;
}
@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;
}
private ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
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;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (!turnOn) {
return bean;
}
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;
}
//符合规范
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);
}
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 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 String generateProxyClassName(Object bean) {
return bean.getClass().getName() + "$EnhanceBySWTracing$" + ThreadLocalRandom.current().nextInt(100);
}
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 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);
if (invAnn != null) {
ctDestinationField.getFieldInfo().addAttribute(invAnn.copy(cp, null));
}
if (visAnn != null) {
ctDestinationField.getFieldInfo().addAttribute(visAnn.copy(cp, null));
}
}
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));
}
}
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 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 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 {
}
public class TracingEnhanceProcessor implements DisposableBean,
BeanPostProcessor, BeanFactoryPostProcessor, ApplicationContextAware {
private final Set<TracingPattern> beanSet = new ConcurrentHashSet<TracingPattern>();
@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;
}
private ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext)
throws BeansException {
this.applicationContext = applicationContext;
}
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;
}
@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;
}
// 符合规范
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.delegator(m, ctDestination);
copyMethodAnnotation(cp, m, newm);
// 是否符合规范,符合则增强
if (checkMatch(m.getName(), matchClassBean.getMethod(),
MatchType.METHOD)) {
enhanceMethod(bean, newm);
}
ctDestination.addMethod(newm);
}
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 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 String generateProxyClassName(Object bean) {
return bean.getClass().getName() + "$EnhanceBySWTracing$"
+ ThreadLocalRandom.current().nextInt(100);
}
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 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);
if (invAnn != null) {
ctDestinationField.getFieldInfo().addAttribute(
invAnn.copy(cp, null));
}
if (visAnn != null) {
ctDestinationField.getFieldInfo().addAttribute(
visAnn.copy(cp, null));
}
}
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));
}
}
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 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 {
}
}
......@@ -10,6 +10,9 @@ import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
public class TracingPatternParser implements BeanDefinitionParser {
private final String TRACE_PROCESSOR_BEAN_NAME = "TraceProcessorBean";
@Override
public BeanDefinition parse(Element element, ParserContext parserContext) {
// 获取Method并处理
......@@ -48,7 +51,14 @@ public class TracingPatternParser implements BeanDefinitionParser {
beanDefinition.getPropertyValues().add(key, value);
}
}
if (!parserContext.getRegistry().containsBeanDefinition(TRACE_PROCESSOR_BEAN_NAME)){
RootBeanDefinition traceProcessorBeanDefinition = new RootBeanDefinition();
traceProcessorBeanDefinition.setBeanClass(TracingEnhanceProcessor.class);
traceProcessorBeanDefinition.setLazyInit(false);
parserContext.getRegistry().registerBeanDefinition(TRACE_PROCESSOR_BEAN_NAME, traceProcessorBeanDefinition);
}
return beanDefinition;
}
}
package com.ai.cloud.skywalking.plugin.spring.extansion;
public class SpringExtensionFactory {
}
package com.ai.cloud.skywalking.plugin.spring.parser;
import org.springframework.beans.factory.config.BeanDefinition;
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;
public class TracingBeanDefinitionParser implements BeanDefinitionParser {
@Override
public BeanDefinition parse(Element element, ParserContext parserContext) {
RootBeanDefinition beanDefinition = new RootBeanDefinition();
String toBeTracingBeanClassName = element.getAttribute("name");
String methodPattern = element.getAttribute("method");
//校验入参
//
return beanDefinition;
}
}
package com.ai.cloud.skywalking.plugin.spring.parser;
import com.ai.cloud.skywalking.plugin.spring.TracingEnhanceProcessor;
import org.springframework.beans.factory.config.BeanDefinition;
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;
public class TracingBeanPostProcessorParser implements BeanDefinitionParser {
@Override
public BeanDefinition parse(Element element, ParserContext parserContext) {
RootBeanDefinition beanDefinition = new RootBeanDefinition();
//
beanDefinition.setBeanClass(TracingEnhanceProcessor.class);
return beanDefinition;
}
}
package com.ai.cloud.skywalking.plugin.spring.parser;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.xml.BeanDefinitionParser;
import org.springframework.beans.factory.xml.ParserContext;
import org.w3c.dom.Element;
public class TracingPackageDefinitionParser implements BeanDefinitionParser {
@Override
public BeanDefinition parse(Element element, ParserContext parserContext) {
return null;
}
}
package com.ai.cloud.skywalking.plugin.spring.schema;
import com.ai.cloud.skywalking.plugin.spring.parser.TracingBeanDefinitionParser;
import com.ai.cloud.skywalking.plugin.spring.parser.TracingBeanPostProcessorParser;
import com.ai.cloud.skywalking.plugin.spring.parser.TracingPackageDefinitionParser;
import org.springframework.beans.factory.xml.NamespaceHandlerSupport;
public class SWNamespaceHandler extends NamespaceHandlerSupport {
@Override
public void init() {
registerBeanDefinitionParser("tracing-class", new TracingBeanDefinitionParser());
registerBeanDefinitionParser("tracing-package", new TracingPackageDefinitionParser());
registerBeanDefinitionParser("tracing", new TracingBeanPostProcessorParser());
}
}
......@@ -11,11 +11,13 @@ public class ConcurrentHashSet<E> extends AbstractSet<E> implements Set<E>, Seri
private static final Object PRESENT = new Object();
private final ConcurrentHashMap<E, Object> map;
public ConcurrentHashSet() {
@SuppressWarnings("unchecked")
public ConcurrentHashSet() {
this.map = new ConcurrentHashMap();
}
public ConcurrentHashSet(int initialCapacity) {
@SuppressWarnings("unchecked")
public ConcurrentHashSet(int initialCapacity) {
this.map = new ConcurrentHashMap(initialCapacity);
}
......
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<xsd:schema xmlns="http://cloud.asiainfo.com/schema/skywalking"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://cloud.asiainfo.com/schema/skywalking">
xmlns:xsd="http://www.w3.org/2001/XMLSchema" targetNamespace="http://cloud.asiainfo.com/schema/skywalking">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace"/>
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="tracing-bean">
<xsd:complexType>
<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="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:element name="trace" type="traceType">
</xsd:element>
<xsd:complexType name="traceType">
<xsd:attribute name="packageName" type="xsd:string" use="required" />
<xsd:attribute name="className" type="xsd:string" use="required" />
<xsd:attribute name="method" type="xsd:string" use="optional"
default="*" />
</xsd:complexType>
</xsd:schema>
\ No newline at end of file
......@@ -14,4 +14,4 @@ public class TestBean {
TestBean testBean = classPathXmlApplicationContext.getBean(TestBean.class);
testBean.testPrintln("Hello World");
}
}
}
\ No newline at end of file
......@@ -4,14 +4,11 @@
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">
<skywalking:trace/>
<!--<skywalking:tracing-bean className="AppTest01" method="testPrintln*" packageName="*"/>-->
<skywalking:trace className="TestBean" method="testPrintln*" packageName="*"/>
<bean class="com.ai.cloud.skywalking.plugin.spring.TestBean" />
</beans>
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册