Provided 4 types match for enhance class:
* byName * byClassAnnotationMatch * byMethodAnnotationMatch * byHierarchyMatch
This commit is contained in:
parent
28b6d8faa4
commit
ea7db2090a
|
|
@ -64,7 +64,7 @@ public abstract class AbstractClassEnhancePluginDefine {
|
|||
DynamicType.Builder<?> newClassBuilder, ClassLoader classLoader) throws PluginException;
|
||||
|
||||
/**
|
||||
* Define the classname of target class.
|
||||
* Define the {@link ClassMatch} for filtering class.
|
||||
*
|
||||
* @return {@link ClassMatch}
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -1,18 +1,16 @@
|
|||
package org.skywalking.apm.agent.core.plugin;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import net.bytebuddy.description.NamedElement;
|
||||
import net.bytebuddy.description.annotation.AnnotationDescription;
|
||||
import net.bytebuddy.description.annotation.AnnotationList;
|
||||
import net.bytebuddy.description.type.TypeDescription;
|
||||
import net.bytebuddy.matcher.ElementMatcher;
|
||||
import org.skywalking.apm.agent.core.plugin.bytebuddy.AbstractJunction;
|
||||
import org.skywalking.apm.agent.core.plugin.match.AnnotationMatch;
|
||||
import org.skywalking.apm.agent.core.plugin.match.ClassAnnotationMatch;
|
||||
import org.skywalking.apm.agent.core.plugin.match.ClassMatch;
|
||||
import org.skywalking.apm.agent.core.plugin.match.IndirectMatch;
|
||||
import org.skywalking.apm.agent.core.plugin.match.NameMatch;
|
||||
|
||||
import static net.bytebuddy.matcher.ElementMatchers.isInterface;
|
||||
|
|
@ -36,7 +34,7 @@ public class PluginFinder {
|
|||
continue;
|
||||
}
|
||||
|
||||
if (match instanceof NameMatch) {
|
||||
if (match instanceof IndirectMatch) {
|
||||
NameMatch nameMatch = (NameMatch)match;
|
||||
nameMatchDefine.put(nameMatch.getClassName(), plugin);
|
||||
} else {
|
||||
|
|
@ -53,17 +51,9 @@ public class PluginFinder {
|
|||
}
|
||||
|
||||
for (AbstractClassEnhancePluginDefine pluginDefine : signatureMatchDefine) {
|
||||
ClassMatch classMatch = pluginDefine.enhanceClass();
|
||||
if (classMatch instanceof AnnotationMatch) {
|
||||
AnnotationMatch annotationMatch = (AnnotationMatch)classMatch;
|
||||
List<String> annotationList = Arrays.asList(annotationMatch.getAnnotations());
|
||||
AnnotationList declaredAnnotations = typeDescription.getDeclaredAnnotations();
|
||||
for (AnnotationDescription annotation : declaredAnnotations) {
|
||||
annotationList.remove(annotation.getAnnotationType().getActualName());
|
||||
}
|
||||
if (annotationList.isEmpty()) {
|
||||
return pluginDefine;
|
||||
}
|
||||
IndirectMatch match = (IndirectMatch)pluginDefine.enhanceClass();
|
||||
if (match.isMatch(typeDescription)) {
|
||||
return pluginDefine;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -80,8 +70,8 @@ public class PluginFinder {
|
|||
judge = judge.and(not(isInterface()));
|
||||
for (AbstractClassEnhancePluginDefine define : signatureMatchDefine) {
|
||||
ClassMatch match = define.enhanceClass();
|
||||
if (match instanceof AnnotationMatch) {
|
||||
judge = judge.or(((AnnotationMatch)match).buildJunction());
|
||||
if (match instanceof ClassAnnotationMatch) {
|
||||
judge = judge.or(((ClassAnnotationMatch)match).buildJunction());
|
||||
}
|
||||
}
|
||||
return judge;
|
||||
|
|
|
|||
|
|
@ -1,40 +0,0 @@
|
|||
package org.skywalking.apm.agent.core.plugin.match;
|
||||
|
||||
import net.bytebuddy.matcher.ElementMatcher;
|
||||
|
||||
import static net.bytebuddy.matcher.ElementMatchers.isAnnotatedWith;
|
||||
import static net.bytebuddy.matcher.ElementMatchers.isInterface;
|
||||
import static net.bytebuddy.matcher.ElementMatchers.named;
|
||||
import static net.bytebuddy.matcher.ElementMatchers.not;
|
||||
|
||||
/**
|
||||
* @author wusheng
|
||||
*/
|
||||
public class AnnotationMatch extends ClassMatch {
|
||||
private String[] annotations;
|
||||
|
||||
public AnnotationMatch(String[] annotations) {
|
||||
this.annotations = annotations;
|
||||
}
|
||||
|
||||
public ElementMatcher.Junction buildJunction() {
|
||||
ElementMatcher.Junction junction = null;
|
||||
for (String annotation : annotations) {
|
||||
if (junction == null) {
|
||||
junction = buildEachAnnotation(annotation);
|
||||
} else {
|
||||
junction = junction.and(buildEachAnnotation(annotation));
|
||||
}
|
||||
}
|
||||
junction = junction.and(not(isInterface()));
|
||||
return junction;
|
||||
}
|
||||
|
||||
private ElementMatcher.Junction buildEachAnnotation(String annotationName) {
|
||||
return isAnnotatedWith(named(annotationName));
|
||||
}
|
||||
|
||||
public String[] getAnnotations() {
|
||||
return annotations;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,64 @@
|
|||
package org.skywalking.apm.agent.core.plugin.match;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import net.bytebuddy.description.annotation.AnnotationDescription;
|
||||
import net.bytebuddy.description.annotation.AnnotationList;
|
||||
import net.bytebuddy.description.type.TypeDescription;
|
||||
import net.bytebuddy.matcher.ElementMatcher;
|
||||
|
||||
import static net.bytebuddy.matcher.ElementMatchers.isAnnotatedWith;
|
||||
import static net.bytebuddy.matcher.ElementMatchers.isInterface;
|
||||
import static net.bytebuddy.matcher.ElementMatchers.named;
|
||||
import static net.bytebuddy.matcher.ElementMatchers.not;
|
||||
|
||||
/**
|
||||
* Match the class by the given annotations in class.
|
||||
*
|
||||
* @author wusheng
|
||||
*/
|
||||
public class ClassAnnotationMatch implements IndirectMatch {
|
||||
private String[] annotations;
|
||||
|
||||
private ClassAnnotationMatch(String[] annotations) {
|
||||
if (annotations == null || annotations.length == 0) {
|
||||
throw new IllegalArgumentException("annotations is null");
|
||||
}
|
||||
this.annotations = annotations;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ElementMatcher.Junction buildJunction() {
|
||||
ElementMatcher.Junction junction = null;
|
||||
for (String annotation : annotations) {
|
||||
if (junction == null) {
|
||||
junction = buildEachAnnotation(annotation);
|
||||
} else {
|
||||
junction = junction.and(buildEachAnnotation(annotation));
|
||||
}
|
||||
}
|
||||
junction = junction.and(not(isInterface()));
|
||||
return junction;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isMatch(TypeDescription typeDescription) {
|
||||
List<String> annotationList = Arrays.asList(annotations);
|
||||
AnnotationList declaredAnnotations = typeDescription.getDeclaredAnnotations();
|
||||
for (AnnotationDescription annotation : declaredAnnotations) {
|
||||
annotationList.remove(annotation.getAnnotationType().getActualName());
|
||||
}
|
||||
if (annotationList.isEmpty()) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private ElementMatcher.Junction buildEachAnnotation(String annotationName) {
|
||||
return isAnnotatedWith(named(annotationName));
|
||||
}
|
||||
|
||||
public static ClassMatch byClassAnnotationMatch(String[] annotations) {
|
||||
return new ClassAnnotationMatch(annotations);
|
||||
}
|
||||
}
|
||||
|
|
@ -3,5 +3,5 @@ package org.skywalking.apm.agent.core.plugin.match;
|
|||
/**
|
||||
* @author wusheng
|
||||
*/
|
||||
public abstract class ClassMatch {
|
||||
public interface ClassMatch {
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,22 +1,52 @@
|
|||
package org.skywalking.apm.agent.core.plugin.match;
|
||||
|
||||
import net.bytebuddy.description.type.TypeDescription;
|
||||
import net.bytebuddy.matcher.ElementMatcher;
|
||||
|
||||
import static net.bytebuddy.matcher.ElementMatchers.hasSuperType;
|
||||
import static net.bytebuddy.matcher.ElementMatchers.isInterface;
|
||||
import static net.bytebuddy.matcher.ElementMatchers.named;
|
||||
import static net.bytebuddy.matcher.ElementMatchers.not;
|
||||
|
||||
/**
|
||||
* Match the class by the given super class or interfaces.
|
||||
*
|
||||
* @author wusheng
|
||||
*/
|
||||
public class HierarchyMatch extends ClassMatch {
|
||||
public class HierarchyMatch implements IndirectMatch {
|
||||
private String[] parentTypes;
|
||||
|
||||
public HierarchyMatch(String[] parentTypes) {
|
||||
private HierarchyMatch(String[] parentTypes) {
|
||||
if (parentTypes == null || parentTypes.length == 0) {
|
||||
throw new IllegalArgumentException("parentTypes is null");
|
||||
}
|
||||
this.parentTypes = parentTypes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ElementMatcher.Junction buildJunction() {
|
||||
return null;
|
||||
ElementMatcher.Junction junction = null;
|
||||
for (String superTypeName : parentTypes) {
|
||||
if (junction == null) {
|
||||
junction = buildEachAnnotation(superTypeName);
|
||||
} else {
|
||||
junction = junction.and(buildEachAnnotation(superTypeName));
|
||||
}
|
||||
}
|
||||
junction = junction.and(not(isInterface()));
|
||||
return junction;
|
||||
}
|
||||
|
||||
private ElementMatcher.Junction buildEachParent(String parentType) {
|
||||
return null;
|
||||
private ElementMatcher.Junction buildEachAnnotation(String superTypeName) {
|
||||
return hasSuperType(named(superTypeName));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isMatch(TypeDescription typeDescription) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public static ClassMatch byHierarchyMatch(String[] parentTypes) {
|
||||
return new HierarchyMatch(parentTypes);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,15 @@
|
|||
package org.skywalking.apm.agent.core.plugin.match;
|
||||
|
||||
import net.bytebuddy.description.type.TypeDescription;
|
||||
import net.bytebuddy.matcher.ElementMatcher;
|
||||
|
||||
/**
|
||||
* All implementations can't direct match the class like {@link NameMatch} did.
|
||||
*
|
||||
* @author wusheng
|
||||
*/
|
||||
public interface IndirectMatch extends ClassMatch {
|
||||
ElementMatcher.Junction buildJunction();
|
||||
|
||||
boolean isMatch(TypeDescription typeDescription);
|
||||
}
|
||||
|
|
@ -0,0 +1,71 @@
|
|||
package org.skywalking.apm.agent.core.plugin.match;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import net.bytebuddy.description.annotation.AnnotationDescription;
|
||||
import net.bytebuddy.description.annotation.AnnotationList;
|
||||
import net.bytebuddy.description.method.MethodDescription;
|
||||
import net.bytebuddy.description.type.TypeDescription;
|
||||
import net.bytebuddy.matcher.ElementMatcher;
|
||||
|
||||
import static net.bytebuddy.matcher.ElementMatchers.declaresMethod;
|
||||
import static net.bytebuddy.matcher.ElementMatchers.isAnnotatedWith;
|
||||
import static net.bytebuddy.matcher.ElementMatchers.isInterface;
|
||||
import static net.bytebuddy.matcher.ElementMatchers.named;
|
||||
import static net.bytebuddy.matcher.ElementMatchers.not;
|
||||
|
||||
/**
|
||||
* Match the class, which has methods with the certain annotations.
|
||||
* This is a very complex match.
|
||||
*
|
||||
* @author wusheng
|
||||
*/
|
||||
public class MethodAnnotationMatch implements IndirectMatch {
|
||||
private String[] annotations;
|
||||
|
||||
private MethodAnnotationMatch(String[] annotations) {
|
||||
if (annotations == null || annotations.length == 0) {
|
||||
throw new IllegalArgumentException("annotations is null");
|
||||
}
|
||||
this.annotations = annotations;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ElementMatcher.Junction buildJunction() {
|
||||
ElementMatcher.Junction junction = null;
|
||||
for (String annotation : annotations) {
|
||||
if (junction == null) {
|
||||
junction = buildEachAnnotation(annotation);
|
||||
} else {
|
||||
junction = junction.and(buildEachAnnotation(annotation));
|
||||
}
|
||||
}
|
||||
junction = declaresMethod(junction).and(not(isInterface()));
|
||||
return junction;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isMatch(TypeDescription typeDescription) {
|
||||
for (MethodDescription.InDefinedShape methodDescription : typeDescription.getDeclaredMethods()) {
|
||||
List<String> annotationList = Arrays.asList(annotations);
|
||||
|
||||
AnnotationList declaredAnnotations = methodDescription.getDeclaredAnnotations();
|
||||
for (AnnotationDescription annotation : declaredAnnotations) {
|
||||
annotationList.remove(annotation.getAnnotationType().getActualName());
|
||||
}
|
||||
if (annotationList.isEmpty()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private ElementMatcher.Junction buildEachAnnotation(String annotationName) {
|
||||
return isAnnotatedWith(named(annotationName));
|
||||
}
|
||||
|
||||
public static ClassMatch byMethodAnnotationMatch(String[] annotations) {
|
||||
return new MethodAnnotationMatch(annotations);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,12 +1,14 @@
|
|||
package org.skywalking.apm.agent.core.plugin.match;
|
||||
|
||||
/**
|
||||
* Match the class with an explicit class name.
|
||||
*
|
||||
* @author wusheng
|
||||
*/
|
||||
public class NameMatch extends ClassMatch {
|
||||
public class NameMatch implements ClassMatch {
|
||||
private String className;
|
||||
|
||||
public NameMatch(String className) {
|
||||
private NameMatch(String className) {
|
||||
this.className = className;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue