You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@skywalking.apache.org by wu...@apache.org on 2020/08/17 02:14:53 UTC

[skywalking] branch master updated: spring annotation enhance (#5320)

This is an automated email from the ASF dual-hosted git repository.

wusheng pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/skywalking.git


The following commit(s) were added to refs/heads/master by this push:
     new a6e45d0  spring annotation enhance (#5320)
a6e45d0 is described below

commit a6e45d04c9b80b20d087650451c8eea27b065253
Author: Evan <31...@users.noreply.github.com>
AuthorDate: Mon Aug 17 10:14:40 2020 +0800

    spring annotation enhance (#5320)
---
 .../core/plugin/match/ClassAnnotationMatch.java    |  2 +-
 .../apm/agent/core/plugin/match/RegexMatch.java    | 67 +++++++++++++++++
 .../apm/agent/core/plugin/match/MatchTest.java     | 84 ++++++++++++++++++++++
 .../core/plugin/match/MatchTestAnnotation.java}    | 22 +++---
 apm-sniffer/config/agent.config                    |  3 +
 .../AbstractSpringBeanInstrumentation.java         | 26 ++++++-
 ...umentation.java => SpringAnnotationConfig.java} | 24 +++----
 .../bean/SpringBeanInstrumentation.java            |  7 +-
 .../component/SpringComponentInstrumentation.java  |  7 +-
 .../SpringRepositoryInstrumentation.java           |  7 +-
 .../services/SpringServicesInstrumentation.java    |  7 +-
 docs/en/setup/service-agent/java-agent/README.md   |  3 +-
 12 files changed, 209 insertions(+), 50 deletions(-)

diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/plugin/match/ClassAnnotationMatch.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/plugin/match/ClassAnnotationMatch.java
index f79fa5b..0d005d0 100644
--- a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/plugin/match/ClassAnnotationMatch.java
+++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/plugin/match/ClassAnnotationMatch.java
@@ -72,7 +72,7 @@ public class ClassAnnotationMatch implements IndirectMatch {
         return isAnnotatedWith(named(annotationName));
     }
 
-    public static ClassMatch byClassAnnotationMatch(String[] annotations) {
+    public static ClassAnnotationMatch byClassAnnotationMatch(String... annotations) {
         return new ClassAnnotationMatch(annotations);
     }
 }
diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/plugin/match/RegexMatch.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/plugin/match/RegexMatch.java
new file mode 100644
index 0000000..b06dddd
--- /dev/null
+++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/plugin/match/RegexMatch.java
@@ -0,0 +1,67 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.skywalking.apm.agent.core.plugin.match;
+
+import net.bytebuddy.description.type.TypeDescription;
+import net.bytebuddy.matcher.ElementMatcher;
+
+import static net.bytebuddy.matcher.ElementMatchers.nameMatches;
+
+/**
+ * Match the class by given class name regex expression.
+ */
+public class RegexMatch implements IndirectMatch {
+    private String[] regexExpressions;
+
+    private RegexMatch(String... regexExpressions) {
+        if (regexExpressions == null || regexExpressions.length == 0) {
+            throw new IllegalArgumentException("annotations is null");
+        }
+        this.regexExpressions = regexExpressions;
+    }
+
+    @Override
+    public ElementMatcher.Junction buildJunction() {
+        ElementMatcher.Junction regexJunction = null;
+        for (String regexExpression : regexExpressions) {
+            if (regexJunction == null) {
+                regexJunction = nameMatches(regexExpression);
+            } else {
+                regexJunction = regexJunction.or(nameMatches(regexExpression));
+            }
+        }
+        return regexJunction;
+    }
+
+    @Override
+    public boolean isMatch(TypeDescription typeDescription) {
+        boolean isMatch = false;
+        for (String matchExpression : regexExpressions) {
+            isMatch = typeDescription.getTypeName().matches(matchExpression);
+            if (isMatch) {
+                break;
+            }
+        }
+        return isMatch;
+    }
+
+    public static RegexMatch byRegexMatch(String... regexExpressions) {
+        return new RegexMatch(regexExpressions);
+    }
+}
\ No newline at end of file
diff --git a/apm-sniffer/apm-agent-core/src/test/java/org/apache/skywalking/apm/agent/core/plugin/match/MatchTest.java b/apm-sniffer/apm-agent-core/src/test/java/org/apache/skywalking/apm/agent/core/plugin/match/MatchTest.java
new file mode 100644
index 0000000..dbacdba
--- /dev/null
+++ b/apm-sniffer/apm-agent-core/src/test/java/org/apache/skywalking/apm/agent/core/plugin/match/MatchTest.java
@@ -0,0 +1,84 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.skywalking.apm.agent.core.plugin.match;
+
+import net.bytebuddy.description.type.TypeDescription;
+import org.apache.skywalking.apm.agent.core.plugin.match.logical.LogicalMatchOperation;
+import org.junit.Assert;
+import org.junit.Test;
+
+import static org.apache.skywalking.apm.agent.core.plugin.match.ClassAnnotationMatch.byClassAnnotationMatch;
+import static org.apache.skywalking.apm.agent.core.plugin.match.RegexMatch.byRegexMatch;
+
+public class MatchTest {
+    private static final String[] REGEX = new String[] {
+        ".*Service.*",
+        ".*Repository.*"
+    };
+
+    @Test
+    public void testRegexMatch() {
+        RegexMatch regexMatch = byRegexMatch(REGEX);
+        TypeDescription typeDefinition = TypeDescription.ForLoadedType.of(TestService.class);
+        Assert.assertTrue(regexMatch.isMatch(typeDefinition));
+        typeDefinition = TypeDescription.ForLoadedType.of(TestDao.class);
+        Assert.assertFalse(regexMatch.isMatch(typeDefinition));
+        typeDefinition = TypeDescription.ForLoadedType.of(TestRepository.class);
+        Assert.assertTrue(regexMatch.isMatch(typeDefinition));
+    }
+
+    @Test
+    public void testAnnotationMatch() {
+        ClassAnnotationMatch classAnnotationMatch = byClassAnnotationMatch(MatchTestAnnotation.class.getName());
+        TypeDescription typeDefinition = TypeDescription.ForLoadedType.of(TestService.class);
+        Assert.assertFalse(classAnnotationMatch.isMatch(typeDefinition));
+        typeDefinition = TypeDescription.ForLoadedType.of(TestDao.class);
+        Assert.assertTrue(classAnnotationMatch.isMatch(typeDefinition));
+        typeDefinition = TypeDescription.ForLoadedType.of(TestRepository.class);
+        Assert.assertTrue(classAnnotationMatch.isMatch(typeDefinition));
+    }
+
+    @Test
+    public void testLogicalMatchOperation() {
+        IndirectMatch match = LogicalMatchOperation.and(
+            byRegexMatch(REGEX),
+            byClassAnnotationMatch(MatchTestAnnotation.class.getName())
+        );
+        TypeDescription typeDefinition = TypeDescription.ForLoadedType.of(TestService.class);
+        Assert.assertFalse(match.isMatch(typeDefinition));
+        typeDefinition = TypeDescription.ForLoadedType.of(TestDao.class);
+        Assert.assertFalse(match.isMatch(typeDefinition));
+        typeDefinition = TypeDescription.ForLoadedType.of(TestRepository.class);
+        Assert.assertTrue(match.isMatch(typeDefinition));
+    }
+
+    public static class TestService {
+
+    }
+
+    @MatchTestAnnotation
+    public static class TestDao {
+
+    }
+
+    @MatchTestAnnotation
+    public static class TestRepository {
+
+    }
+}  
\ No newline at end of file
diff --git a/apm-sniffer/optional-plugins/optional-spring-plugins/spring-annotation-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/annotations/bean/SpringBeanInstrumentation.java b/apm-sniffer/apm-agent-core/src/test/java/org/apache/skywalking/apm/agent/core/plugin/match/MatchTestAnnotation.java
similarity index 55%
copy from apm-sniffer/optional-plugins/optional-spring-plugins/spring-annotation-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/annotations/bean/SpringBeanInstrumentation.java
copy to apm-sniffer/apm-agent-core/src/test/java/org/apache/skywalking/apm/agent/core/plugin/match/MatchTestAnnotation.java
index 845a5a8..7bf972f 100644
--- a/apm-sniffer/optional-plugins/optional-spring-plugins/spring-annotation-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/annotations/bean/SpringBeanInstrumentation.java
+++ b/apm-sniffer/apm-agent-core/src/test/java/org/apache/skywalking/apm/agent/core/plugin/match/MatchTestAnnotation.java
@@ -16,19 +16,13 @@
  *
  */
 
-package org.apache.skywalking.apm.plugin.spring.annotations.bean;
+package org.apache.skywalking.apm.agent.core.plugin.match;
 
-import org.apache.skywalking.apm.agent.core.plugin.match.ClassMatch;
-import org.apache.skywalking.apm.plugin.spring.annotations.AbstractSpringBeanInstrumentation;
+import java.lang.annotation.Inherited;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 
-import static org.apache.skywalking.apm.agent.core.plugin.match.ClassAnnotationMatch.byClassAnnotationMatch;
-
-public class SpringBeanInstrumentation extends AbstractSpringBeanInstrumentation {
-
-    public static final String ENHANCE_ANNOTATION = "org.springframework.context.annotation.Bean";
-
-    @Override
-    protected ClassMatch enhanceClass() {
-        return byClassAnnotationMatch(new String[] {ENHANCE_ANNOTATION});
-    }
-}
+@Retention(RetentionPolicy.RUNTIME)
+@Inherited
+public @interface MatchTestAnnotation {
+}
\ No newline at end of file
diff --git a/apm-sniffer/config/agent.config b/apm-sniffer/config/agent.config
index 9979c7c..ee511865 100644
--- a/apm-sniffer/config/agent.config
+++ b/apm-sniffer/config/agent.config
@@ -93,3 +93,6 @@ logging.level=${SW_LOGGING_LEVEL:INFO}
 
 # Exclude activated plugins
 # plugin.exclude_plugins=${SW_EXCLUDE_PLUGINS:""}
+
+# Match spring bean with regex expression for classname
+# plugin.springannotation.classname_match_regex_expression=${SW_SPRINGANNOTATION_CLASSNAME_MATCH_REGEX_EXPRESSION:""}
diff --git a/apm-sniffer/optional-plugins/optional-spring-plugins/spring-annotation-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/annotations/AbstractSpringBeanInstrumentation.java b/apm-sniffer/optional-plugins/optional-spring-plugins/spring-annotation-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/annotations/AbstractSpringBeanInstrumentation.java
index 940c259..70ee287 100644
--- a/apm-sniffer/optional-plugins/optional-spring-plugins/spring-annotation-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/annotations/AbstractSpringBeanInstrumentation.java
+++ b/apm-sniffer/optional-plugins/optional-spring-plugins/spring-annotation-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/annotations/AbstractSpringBeanInstrumentation.java
@@ -24,11 +24,17 @@ import org.apache.skywalking.apm.agent.core.plugin.interceptor.ConstructorInterc
 import org.apache.skywalking.apm.agent.core.plugin.interceptor.DeclaredInstanceMethodsInterceptPoint;
 import org.apache.skywalking.apm.agent.core.plugin.interceptor.InstanceMethodsInterceptPoint;
 import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.ClassInstanceMethodsEnhancePluginDefine;
+import org.apache.skywalking.apm.agent.core.plugin.match.ClassMatch;
+import org.apache.skywalking.apm.agent.core.plugin.match.logical.LogicalMatchOperation;
+import org.apache.skywalking.apm.util.StringUtil;
 
 import static net.bytebuddy.matcher.ElementMatchers.isDeclaredBy;
 import static net.bytebuddy.matcher.ElementMatchers.isPublic;
 import static net.bytebuddy.matcher.ElementMatchers.named;
 import static net.bytebuddy.matcher.ElementMatchers.not;
+import static org.apache.skywalking.apm.agent.core.plugin.match.ClassAnnotationMatch.byClassAnnotationMatch;
+import static org.apache.skywalking.apm.agent.core.plugin.match.RegexMatch.byRegexMatch;
+import static org.apache.skywalking.apm.plugin.spring.annotations.SpringAnnotationConfig.Plugin.SpringAnnotation.CLASSNAME_MATCH_REGEX_EXPRESSION;
 
 public abstract class AbstractSpringBeanInstrumentation extends ClassInstanceMethodsEnhancePluginDefine {
     private static final String INTERCEPTOR_CLASS = "org.apache.skywalking.apm.plugin.spring.annotations.SpringAnnotationInterceptor";
@@ -46,8 +52,9 @@ public abstract class AbstractSpringBeanInstrumentation extends ClassInstanceMet
             new DeclaredInstanceMethodsInterceptPoint() {
                 @Override
                 public ElementMatcher<MethodDescription> getMethodsMatcher() {
-                    return isPublic().and(not(isDeclaredBy(Object.class)).and(not(named(INTERCEPT_GET_SKYWALKING_DYNAMIC_FIELD_METHOD)))
-                                                                         .and(not(named(INTERCEPT_SET_SKYWALKING_DYNAMIC_FIELD_METHOD))));
+                    return isPublic().and(not(isDeclaredBy(Object.class))
+                                              .and(not(named(INTERCEPT_GET_SKYWALKING_DYNAMIC_FIELD_METHOD)))
+                                              .and(not(named(INTERCEPT_SET_SKYWALKING_DYNAMIC_FIELD_METHOD))));
                 }
 
                 @Override
@@ -62,4 +69,19 @@ public abstract class AbstractSpringBeanInstrumentation extends ClassInstanceMet
             }
         };
     }
+
+    @Override
+    protected ClassMatch enhanceClass() {
+        if (StringUtil.isEmpty(CLASSNAME_MATCH_REGEX_EXPRESSION)) {
+            return byClassAnnotationMatch(getEnhanceAnnotation());
+        } else {
+            return LogicalMatchOperation.and(
+                byRegexMatch(CLASSNAME_MATCH_REGEX_EXPRESSION.split(",")),
+                byClassAnnotationMatch(getEnhanceAnnotation())
+            );
+        }
+    }
+
+    protected abstract String getEnhanceAnnotation();
+
 }
diff --git a/apm-sniffer/optional-plugins/optional-spring-plugins/spring-annotation-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/annotations/bean/SpringBeanInstrumentation.java b/apm-sniffer/optional-plugins/optional-spring-plugins/spring-annotation-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/annotations/SpringAnnotationConfig.java
similarity index 55%
copy from apm-sniffer/optional-plugins/optional-spring-plugins/spring-annotation-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/annotations/bean/SpringBeanInstrumentation.java
copy to apm-sniffer/optional-plugins/optional-spring-plugins/spring-annotation-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/annotations/SpringAnnotationConfig.java
index 845a5a8..715e295 100644
--- a/apm-sniffer/optional-plugins/optional-spring-plugins/spring-annotation-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/annotations/bean/SpringBeanInstrumentation.java
+++ b/apm-sniffer/optional-plugins/optional-spring-plugins/spring-annotation-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/annotations/SpringAnnotationConfig.java
@@ -16,19 +16,19 @@
  *
  */
 
-package org.apache.skywalking.apm.plugin.spring.annotations.bean;
+package org.apache.skywalking.apm.plugin.spring.annotations;
 
-import org.apache.skywalking.apm.agent.core.plugin.match.ClassMatch;
-import org.apache.skywalking.apm.plugin.spring.annotations.AbstractSpringBeanInstrumentation;
+import org.apache.skywalking.apm.agent.core.boot.PluginConfig;
 
-import static org.apache.skywalking.apm.agent.core.plugin.match.ClassAnnotationMatch.byClassAnnotationMatch;
+public class SpringAnnotationConfig {
 
-public class SpringBeanInstrumentation extends AbstractSpringBeanInstrumentation {
-
-    public static final String ENHANCE_ANNOTATION = "org.springframework.context.annotation.Bean";
-
-    @Override
-    protected ClassMatch enhanceClass() {
-        return byClassAnnotationMatch(new String[] {ENHANCE_ANNOTATION});
+    public static class Plugin {
+        @PluginConfig(root = SpringAnnotationConfig.class)
+        public static class SpringAnnotation {
+            /**
+             * regex expression to match spring bean classname
+             */
+            public static String CLASSNAME_MATCH_REGEX_EXPRESSION = "";
+        }
     }
-}
+}
\ No newline at end of file
diff --git a/apm-sniffer/optional-plugins/optional-spring-plugins/spring-annotation-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/annotations/bean/SpringBeanInstrumentation.java b/apm-sniffer/optional-plugins/optional-spring-plugins/spring-annotation-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/annotations/bean/SpringBeanInstrumentation.java
index 845a5a8..d97d3b3 100644
--- a/apm-sniffer/optional-plugins/optional-spring-plugins/spring-annotation-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/annotations/bean/SpringBeanInstrumentation.java
+++ b/apm-sniffer/optional-plugins/optional-spring-plugins/spring-annotation-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/annotations/bean/SpringBeanInstrumentation.java
@@ -18,17 +18,14 @@
 
 package org.apache.skywalking.apm.plugin.spring.annotations.bean;
 
-import org.apache.skywalking.apm.agent.core.plugin.match.ClassMatch;
 import org.apache.skywalking.apm.plugin.spring.annotations.AbstractSpringBeanInstrumentation;
 
-import static org.apache.skywalking.apm.agent.core.plugin.match.ClassAnnotationMatch.byClassAnnotationMatch;
-
 public class SpringBeanInstrumentation extends AbstractSpringBeanInstrumentation {
 
     public static final String ENHANCE_ANNOTATION = "org.springframework.context.annotation.Bean";
 
     @Override
-    protected ClassMatch enhanceClass() {
-        return byClassAnnotationMatch(new String[] {ENHANCE_ANNOTATION});
+    protected String getEnhanceAnnotation() {
+        return ENHANCE_ANNOTATION;
     }
 }
diff --git a/apm-sniffer/optional-plugins/optional-spring-plugins/spring-annotation-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/annotations/component/SpringComponentInstrumentation.java b/apm-sniffer/optional-plugins/optional-spring-plugins/spring-annotation-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/annotations/component/SpringComponentInstrumentation.java
index 8cf8f68..5d74596 100644
--- a/apm-sniffer/optional-plugins/optional-spring-plugins/spring-annotation-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/annotations/component/SpringComponentInstrumentation.java
+++ b/apm-sniffer/optional-plugins/optional-spring-plugins/spring-annotation-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/annotations/component/SpringComponentInstrumentation.java
@@ -18,17 +18,14 @@
 
 package org.apache.skywalking.apm.plugin.spring.annotations.component;
 
-import org.apache.skywalking.apm.agent.core.plugin.match.ClassMatch;
 import org.apache.skywalking.apm.plugin.spring.annotations.AbstractSpringBeanInstrumentation;
 
-import static org.apache.skywalking.apm.agent.core.plugin.match.ClassAnnotationMatch.byClassAnnotationMatch;
-
 public class SpringComponentInstrumentation extends AbstractSpringBeanInstrumentation {
 
     public static final String ENHANCE_ANNOTATION = "org.springframework.stereotype.Component";
 
     @Override
-    protected ClassMatch enhanceClass() {
-        return byClassAnnotationMatch(new String[] {ENHANCE_ANNOTATION});
+    protected String getEnhanceAnnotation() {
+        return ENHANCE_ANNOTATION;
     }
 }
diff --git a/apm-sniffer/optional-plugins/optional-spring-plugins/spring-annotation-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/annotations/repository/SpringRepositoryInstrumentation.java b/apm-sniffer/optional-plugins/optional-spring-plugins/spring-annotation-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/annotations/repository/SpringRepositoryInstrumentation.java
index 6f7cfa2..442fa4a 100644
--- a/apm-sniffer/optional-plugins/optional-spring-plugins/spring-annotation-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/annotations/repository/SpringRepositoryInstrumentation.java
+++ b/apm-sniffer/optional-plugins/optional-spring-plugins/spring-annotation-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/annotations/repository/SpringRepositoryInstrumentation.java
@@ -18,17 +18,14 @@
 
 package org.apache.skywalking.apm.plugin.spring.annotations.repository;
 
-import org.apache.skywalking.apm.agent.core.plugin.match.ClassMatch;
 import org.apache.skywalking.apm.plugin.spring.annotations.AbstractSpringBeanInstrumentation;
 
-import static org.apache.skywalking.apm.agent.core.plugin.match.ClassAnnotationMatch.byClassAnnotationMatch;
-
 public class SpringRepositoryInstrumentation extends AbstractSpringBeanInstrumentation {
 
     public static final String ENHANCE_ANNOTATION = "org.springframework.stereotype.Repository";
 
     @Override
-    protected ClassMatch enhanceClass() {
-        return byClassAnnotationMatch(new String[] {ENHANCE_ANNOTATION});
+    protected String getEnhanceAnnotation() {
+        return ENHANCE_ANNOTATION;
     }
 }
diff --git a/apm-sniffer/optional-plugins/optional-spring-plugins/spring-annotation-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/annotations/services/SpringServicesInstrumentation.java b/apm-sniffer/optional-plugins/optional-spring-plugins/spring-annotation-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/annotations/services/SpringServicesInstrumentation.java
index 0a3f454..891db2e 100644
--- a/apm-sniffer/optional-plugins/optional-spring-plugins/spring-annotation-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/annotations/services/SpringServicesInstrumentation.java
+++ b/apm-sniffer/optional-plugins/optional-spring-plugins/spring-annotation-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/annotations/services/SpringServicesInstrumentation.java
@@ -18,17 +18,14 @@
 
 package org.apache.skywalking.apm.plugin.spring.annotations.services;
 
-import org.apache.skywalking.apm.agent.core.plugin.match.ClassMatch;
 import org.apache.skywalking.apm.plugin.spring.annotations.AbstractSpringBeanInstrumentation;
 
-import static org.apache.skywalking.apm.agent.core.plugin.match.ClassAnnotationMatch.byClassAnnotationMatch;
-
 public class SpringServicesInstrumentation extends AbstractSpringBeanInstrumentation {
 
     public static final String ENHANCE_ANNOTATION = "org.springframework.stereotype.Service";
 
     @Override
-    protected ClassMatch enhanceClass() {
-        return byClassAnnotationMatch(new String[] {ENHANCE_ANNOTATION});
+    protected String getEnhanceAnnotation() {
+        return ENHANCE_ANNOTATION;
     }
 }
diff --git a/docs/en/setup/service-agent/java-agent/README.md b/docs/en/setup/service-agent/java-agent/README.md
index 4db51cf..f12bd28 100755
--- a/docs/en/setup/service-agent/java-agent/README.md
+++ b/docs/en/setup/service-agent/java-agent/README.md
@@ -112,7 +112,6 @@ property key | Description | Default |
 `meter.max_meter_size`| Max size of the meter pool |`500`|
 `plugin.peer_max_length `|Peer maximum description limit.|`200`|
 `plugin.exclude_plugins `|Exclude some plugins define in plugins dir.Plugin names is defined in [Agent plugin list](Plugin-list.md)|`""`|
-
 `plugin.mongodb.trace_param`|If true, trace all the parameters in MongoDB access, default is false. Only trace the operation, not include parameters.|`false`|
 `plugin.mongodb.filter_length_limit`|If set to positive number, the `WriteRequest.params` would be truncated to this length, otherwise it would be completely saved, which may cause performance problem.|`256`|
 `plugin.elasticsearch.trace_dsl`|If true, trace all the DSL(Domain Specific Language) in ElasticSearch access, default is false.|`false`|
@@ -151,6 +150,8 @@ property key | Description | Default |
 `plugin.kafka.topic_segment` | Specify which Kafka topic name for traces data to report to. | `skywalking_segments` |
 `plugin.kafka.topic_profilings` | Specify which Kafka topic name for Thread Profiling snapshot to report to. | `skywalking_profilings` |
 `plugin.kafka.topic_management` | Specify which Kafka topic name for the register or heartbeat data of Service Instance to report to. | `skywalking_managements` |
+`plugin.springannotation.classname_match_regex_expression` |  Match spring beans with regex expression for the class name. Multiple expressions could be separated by a comma. This only works when `Spring annotation plugin` has been activated. | `All the spring beans tagged with @Bean,@Service,@Dao, or @Repository.` |
+
 
 ## Optional Plugins
 Java agent plugins are all pluggable. Optional plugins could be provided in `optional-plugins` folder under agent or 3rd party repositories.