From a0a84222d71f6e16efb70805e9d355280e1aea8c Mon Sep 17 00:00:00 2001
From: cvictory <shenglicao2@gmail.com>
Date: Fri, 25 Jan 2019 10:54:45 +0800
Subject: [PATCH 1/5] fix #2842. remove duplicate SPI definitions for 2.7.x

---
 dubbo-all/pom.xml                           | 12 ++++++++++++
 dubbo-container/dubbo-container-api/pom.xml |  3 +--
 pom.xml                                     |  1 -
 3 files changed, 13 insertions(+), 3 deletions(-)

diff --git a/dubbo-all/pom.xml b/dubbo-all/pom.xml
index 8c46af627db..15fd731d706 100644
--- a/dubbo-all/pom.xml
+++ b/dubbo-all/pom.xml
@@ -614,6 +614,18 @@
                                     </resource>
                                 </transformer>
                             </transformers>
+                            <filters>
+                                <filter>
+                                    <artifact>org.apache.dubbo:dubbo</artifact>
+                                    <excludes>
+                                        <!-- These two line is optional, it can remove some warn log -->
+                                        <exclude>com/**</exclude>
+                                        <exclude>org/**</exclude>
+                                        <!-- This one is required -->
+                                        <exclude>META-INF/dubbo/**</exclude>
+                                    </excludes>
+                                </filter>
+                            </filters>
                         </configuration>
                     </execution>
                 </executions>
diff --git a/dubbo-container/dubbo-container-api/pom.xml b/dubbo-container/dubbo-container-api/pom.xml
index 2e1f544064f..2c1e9100af5 100644
--- a/dubbo-container/dubbo-container-api/pom.xml
+++ b/dubbo-container/dubbo-container-api/pom.xml
@@ -47,9 +47,8 @@
                             <mainClass>org.apache.dubbo.container.Main</mainClass>
                         </manifest>
                     </archive>
-                    <forceCreation>true</forceCreation>
                 </configuration>
             </plugin>
         </plugins>
     </build>
-</project>
\ No newline at end of file
+</project>
diff --git a/pom.xml b/pom.xml
index 4cbb67e5b46..8f1a39b7201 100644
--- a/pom.xml
+++ b/pom.xml
@@ -389,7 +389,6 @@
                             <Implementation-Version>${project.version}</Implementation-Version>
                         </manifestEntries>
                     </archive>
-                    <forceCreation>true</forceCreation>
                 </configuration>
             </plugin>
             <plugin>

From 19824c3a9d436b5a19bb9cc211935ae5750d2314 Mon Sep 17 00:00:00 2001
From: cvictory <shenglicao2@gmail.com>
Date: Thu, 21 Feb 2019 10:42:06 +0800
Subject: [PATCH 2/5] fix: rename the thread name from
 DubboRegistryFailedRetryTimer to DubboMetadataReportRetryTimer in
 MetadataReportRetry

---
 .../dubbo/metadata/support/AbstractMetadataReport.java      | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/dubbo-metadata-report/dubbo-metadata-report-api/src/main/java/org/apache/dubbo/metadata/support/AbstractMetadataReport.java b/dubbo-metadata-report/dubbo-metadata-report-api/src/main/java/org/apache/dubbo/metadata/support/AbstractMetadataReport.java
index 6080fa58f82..95b44f44927 100644
--- a/dubbo-metadata-report/dubbo-metadata-report-api/src/main/java/org/apache/dubbo/metadata/support/AbstractMetadataReport.java
+++ b/dubbo-metadata-report/dubbo-metadata-report-api/src/main/java/org/apache/dubbo/metadata/support/AbstractMetadataReport.java
@@ -62,7 +62,7 @@ public abstract class AbstractMetadataReport implements MetadataReport {
     // Log output
     protected final Logger logger = LoggerFactory.getLogger(getClass());
 
-    // Local disk cache, where the special key value.registries records the list of registry centers, and the others are the list of notified service providers
+    // Local disk cache, where the special key value.registries records the list of metadata centers, and the others are the list of notified service providers
     final Properties properties = new Properties();
     private final ExecutorService reportCacheExecutor = Executors.newFixedThreadPool(1, new NamedThreadFactory("DubboSaveMetadataReport", true));
     final Map<MetadataIdentifier, Object> allMetadataReports = new ConcurrentHashMap<>(4);
@@ -336,7 +336,7 @@ long calculateStartTime() {
     class MetadataReportRetry {
         protected final Logger logger = LoggerFactory.getLogger(getClass());
 
-        final ScheduledExecutorService retryExecutor = Executors.newScheduledThreadPool(0, new NamedThreadFactory("DubboRegistryFailedRetryTimer", true));
+        final ScheduledExecutorService retryExecutor = Executors.newScheduledThreadPool(0, new NamedThreadFactory("DubboMetadataReportRetryTimer", true));
         volatile ScheduledFuture retryScheduledFuture;
         AtomicInteger retryCounter = new AtomicInteger(0);
         // retry task schedule period
@@ -358,7 +358,7 @@ void startRetryTask() {
                         retryScheduledFuture = retryExecutor.scheduleWithFixedDelay(new Runnable() {
                             @Override
                             public void run() {
-                                // Check and connect to the registry
+                                // Check and connect to the metadata
                                 try {
                                     int times = retryCounter.incrementAndGet();
                                     logger.info("start to retry task for metadata report. retry times:" + times);

From 574ce03800b59b4282fdd777da0036d8c3ac84fc Mon Sep 17 00:00:00 2001
From: cvictory <shenglicao2@gmail.com>
Date: Mon, 4 Mar 2019 16:28:20 +0800
Subject: [PATCH 3/5] fix #2045. support method annotation

---
 .../apache/dubbo/config/ArgumentConfig.java   | 12 +++-
 .../org/apache/dubbo/config/MethodConfig.java | 36 +++++++++-
 .../apache/dubbo/config/ReferenceConfig.java  |  1 +
 .../apache/dubbo/config/ServiceConfig.java    |  1 +
 .../dubbo/config/annotation/Argument.java     | 44 ++++++++++++
 .../dubbo/config/annotation/Method.java       | 69 +++++++++++++++++++
 .../dubbo/config/annotation/Reference.java    |  6 ++
 .../dubbo/config/annotation/Service.java      |  6 ++
 .../dubbo/config/AbstractConfigTest.java      | 19 +++++
 .../apache/dubbo/config/MethodConfigTest.java | 54 ++++++++++++++-
 .../dubbo/config/ReferenceConfigTest.java     | 31 +++++++++
 .../annotation/ReferenceBeanBuilder.java      | 13 ++++
 .../ServiceAnnotationBeanPostProcessor.java   |  8 ++-
 .../config/spring/util/AnnotationUtils.java   | 13 +++-
 .../annotation/consumer/AnnotationAction.java |  5 +-
 15 files changed, 311 insertions(+), 7 deletions(-)
 create mode 100644 dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/annotation/Argument.java
 create mode 100644 dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/annotation/Method.java

diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ArgumentConfig.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ArgumentConfig.java
index 61db01f28fd..74d906cf2ec 100644
--- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ArgumentConfig.java
+++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ArgumentConfig.java
@@ -16,6 +16,7 @@
  */
 package org.apache.dubbo.config;
 
+import org.apache.dubbo.config.annotation.Argument;
 import org.apache.dubbo.config.support.Parameter;
 
 import java.io.Serializable;
@@ -44,6 +45,15 @@ public class ArgumentConfig implements Serializable {
      */
     private Boolean callback;
 
+    public ArgumentConfig() {
+    }
+
+    public ArgumentConfig(Argument argument) {
+        this.index = argument.index();
+        this.type = argument.type();
+        this.callback = argument.callback();
+    }
+
     @Parameter(excluded = true)
     public Integer getIndex() {
         return index;
@@ -70,4 +80,4 @@ public Boolean isCallback() {
         return callback;
     }
 
-}
\ No newline at end of file
+}
diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/MethodConfig.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/MethodConfig.java
index d65c6659a41..b52d7943914 100644
--- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/MethodConfig.java
+++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/MethodConfig.java
@@ -18,8 +18,11 @@
 
 import org.apache.dubbo.common.Constants;
 import org.apache.dubbo.common.utils.StringUtils;
+import org.apache.dubbo.config.annotation.Method;
 import org.apache.dubbo.config.support.Parameter;
 
+import java.util.ArrayList;
+import java.util.Collections;
 import java.util.List;
 
 /**
@@ -117,6 +120,37 @@ public String getName() {
         return name;
     }
 
+    public MethodConfig() {
+    }
+
+    public MethodConfig(Method method) {
+        appendAnnotation(Method.class, method);
+        this.setReturn(method.isReturn());
+        this.setOninvoke(method.oninvoke());
+        this.setOnreturn(method.onreturn());
+        this.setOnthrow(method.onthrow());
+        if (method.arguments() != null && method.arguments().length != 0) {
+            List<ArgumentConfig> argumentConfigs = new ArrayList<ArgumentConfig>(method.arguments().length);
+            this.setArguments(argumentConfigs);
+            for (int i = 0; i < method.arguments().length; i++) {
+                ArgumentConfig argumentConfig = new ArgumentConfig(method.arguments()[i]);
+                argumentConfigs.add(argumentConfig);
+            }
+        }
+    }
+
+    public static List<MethodConfig> constructMethodConfig(Method[] methods) {
+        if (methods != null && methods.length != 0) {
+            List<MethodConfig> methodConfigs = new ArrayList<MethodConfig>(methods.length);
+            for (int i = 0; i < methods.length; i++) {
+                MethodConfig methodConfig = new MethodConfig(methods[i]);
+                methodConfigs.add(methodConfig);
+            }
+            return methodConfigs;
+        }
+        return Collections.emptyList();
+    }
+
     public void setName(String name) {
         checkMethodName("name", name);
         this.name = name;
@@ -279,4 +313,4 @@ public String getPrefix() {
                 + (StringUtils.isEmpty(serviceId) ? "" : ("." + serviceId))
                 + "." + getName();
     }
-}
\ No newline at end of file
+}
diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ReferenceConfig.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ReferenceConfig.java
index ceacdb2863b..cfbf6708ef0 100644
--- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ReferenceConfig.java
+++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ReferenceConfig.java
@@ -178,6 +178,7 @@ public ReferenceConfig() {
 
     public ReferenceConfig(Reference reference) {
         appendAnnotation(Reference.class, reference);
+        setMethods(MethodConfig.constructMethodConfig(reference.methods()));
     }
 
     public URL toUrl() {
diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ServiceConfig.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ServiceConfig.java
index 73fd83ffa51..8ab29c90462 100644
--- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ServiceConfig.java
+++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ServiceConfig.java
@@ -168,6 +168,7 @@ public ServiceConfig() {
 
     public ServiceConfig(Service service) {
         appendAnnotation(Service.class, service);
+        setMethods(MethodConfig.constructMethodConfig(service.methods()));
     }
 
     @Deprecated
diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/annotation/Argument.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/annotation/Argument.java
new file mode 100644
index 00000000000..6a0da8ea8d9
--- /dev/null
+++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/annotation/Argument.java
@@ -0,0 +1,44 @@
+/*
+ * 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.dubbo.config.annotation;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Inherited;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * @since 2.6.5
+ *
+ * 2018/9/29
+ */
+@Documented
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.ANNOTATION_TYPE})
+@Inherited
+public @interface Argument {
+    //argument: index -1 represents not set
+    int index() default -1;
+
+    //argument type
+    String type() default "";
+
+    //callback interface
+    boolean callback() default false;
+}
diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/annotation/Method.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/annotation/Method.java
new file mode 100644
index 00000000000..0cdc97cf814
--- /dev/null
+++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/annotation/Method.java
@@ -0,0 +1,69 @@
+/*
+ * 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.dubbo.config.annotation;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Inherited;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * @since 2.6.5
+ *  *
+ *  * 2018/9/29
+ */
+@Documented
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.ANNOTATION_TYPE})
+@Inherited
+public @interface Method {
+    String name();
+
+    int timeout() default -1;
+
+    int retries() default -1;
+
+    String loadbalance() default "";
+
+    boolean async() default false;
+
+    boolean sent() default true;
+
+    int actives() default 0;
+
+    int executes() default 0;
+
+    boolean deprecated() default false;
+
+    boolean sticky() default false;
+
+    boolean isReturn() default true;
+
+    String oninvoke() default "";
+
+    String onreturn() default "";
+
+    String onthrow() default "";
+
+    String cache() default "";
+
+    String validation() default "";
+
+    Argument[] arguments() default {};
+}
diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/annotation/Reference.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/annotation/Reference.java
index 63e2cd5f1d1..7ed287ee2f0 100644
--- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/annotation/Reference.java
+++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/annotation/Reference.java
@@ -256,4 +256,10 @@
      * Protocol spring bean names
      */
     String protocol() default "";
+
+    /**
+     * methods support
+     * @return
+     */
+    Method[] methods() default {};
 }
diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/annotation/Service.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/annotation/Service.java
index 6f956f50c05..2e6f9b684a7 100644
--- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/annotation/Service.java
+++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/annotation/Service.java
@@ -268,4 +268,10 @@
      * Service tag name
      */
     String tag() default "";
+
+    /**
+     * methods support
+     * @return
+     */
+    Method[] methods() default {};
 }
diff --git a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/AbstractConfigTest.java b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/AbstractConfigTest.java
index d95b2de84a9..2d40cc369fd 100644
--- a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/AbstractConfigTest.java
+++ b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/AbstractConfigTest.java
@@ -467,6 +467,12 @@ public void tetMetaData() {
         Assertions.assertNull(metaData.get("key2"));
     }
 
+    @Retention(RetentionPolicy.RUNTIME)
+    @Target({ElementType.ANNOTATION_TYPE})
+    public @interface ConfigField {
+        String value() default "";
+    }
+
     @Retention(RetentionPolicy.RUNTIME)
     @Target({ElementType.FIELD, ElementType.METHOD, ElementType.ANNOTATION_TYPE})
     public @interface Config {
@@ -479,6 +485,10 @@ public void tetMetaData() {
         String[] listener() default {};
 
         String[] parameters() default {};
+
+        ConfigField[] configFields() default {};
+
+        ConfigField configField() default @ConfigField;
     }
 
     private static class OverrideConfig extends AbstractInterfaceConfig {
@@ -735,6 +745,7 @@ private static class AnnotationConfig extends AbstractConfig {
         private String filter;
         private String listener;
         private Map<String, String> parameters;
+        private String[] configFields;
 
         public Class getInterface() {
             return interfaceClass;
@@ -767,5 +778,13 @@ public Map<String, String> getParameters() {
         public void setParameters(Map<String, String> parameters) {
             this.parameters = parameters;
         }
+
+        public String[] getConfigFields() {
+            return configFields;
+        }
+
+        public void setConfigFields(String[] configFields) {
+            this.configFields = configFields;
+        }
     }
 }
diff --git a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/MethodConfigTest.java b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/MethodConfigTest.java
index 862c9991e0c..1d976d7e4ee 100644
--- a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/MethodConfigTest.java
+++ b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/MethodConfigTest.java
@@ -18,23 +18,75 @@
 package org.apache.dubbo.config;
 
 import org.apache.dubbo.common.Constants;
+import org.apache.dubbo.config.annotation.Argument;
+import org.apache.dubbo.config.annotation.Method;
+import org.apache.dubbo.config.annotation.Reference;
 
 import org.hamcrest.Matchers;
 import org.junit.jupiter.api.Test;
 
 import java.util.Collections;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
 
+import static org.hamcrest.MatcherAssert.assertThat;
 import static org.hamcrest.Matchers.contains;
 import static org.hamcrest.Matchers.equalTo;
 import static org.hamcrest.Matchers.hasEntry;
 import static org.hamcrest.Matchers.hasKey;
 import static org.hamcrest.Matchers.is;
 import static org.hamcrest.Matchers.not;
-import static org.hamcrest.MatcherAssert.assertThat;
 
 public class MethodConfigTest {
+    private static final String METHOD_NAME = "sayHello";
+    private static final int TIMEOUT = 1300;
+    private static final int RETRIES = 4;
+    private static final String LOADBALANCE = "random";
+    private static final boolean ASYNC = true;
+    private static final int ACTIVES = 3;
+    private static final int EXECUTES = 5;
+    private static final boolean DEPERECATED = true;
+    private static final boolean STICKY = true;
+    private static final String ONINVOKE = "i";
+    private static final String ONTHROW = "t";
+    private static final String ONRETURN = "r";
+    private static final String CACHE = "c";
+    private static final String VALIDATION = "v";
+    private static final int ARGUMENTS_INDEX = 24;
+    private static final boolean ARGUMENTS_CALLBACK = true;
+    private static final String ARGUMENTS_TYPE = "sss";
+
+    @Reference(methods = {@Method(name = METHOD_NAME, timeout = TIMEOUT, retries = RETRIES, loadbalance = LOADBALANCE, async = ASYNC,
+            actives = ACTIVES, executes = EXECUTES, deprecated = DEPERECATED, sticky = STICKY, oninvoke = ONINVOKE, onthrow = ONTHROW, onreturn = ONRETURN, cache = CACHE, validation = VALIDATION,
+            arguments = {@Argument(index = ARGUMENTS_INDEX, callback = ARGUMENTS_CALLBACK, type = ARGUMENTS_TYPE)})})
+    private String testField;
+
+    @Test
+    public void testStaticConstructor() throws NoSuchFieldException {
+        Method[] methods = this.getClass().getDeclaredField("testField").getAnnotation(Reference.class).methods();
+        List<MethodConfig> methodConfigs = MethodConfig.constructMethodConfig(methods);
+        MethodConfig methodConfig = methodConfigs.get(0);
+
+        assertThat(METHOD_NAME, equalTo(methodConfig.getName()));
+        assertThat(TIMEOUT, equalTo(methodConfig.getTimeout().intValue()));
+        assertThat(RETRIES, equalTo(methodConfig.getRetries().intValue()));
+        assertThat(LOADBALANCE, equalTo(methodConfig.getLoadbalance()));
+        assertThat(ASYNC, equalTo(methodConfig.isAsync()));
+        assertThat(ACTIVES, equalTo(methodConfig.getActives().intValue()));
+        assertThat(EXECUTES, equalTo(methodConfig.getExecutes().intValue()));
+        assertThat(DEPERECATED, equalTo(methodConfig.getDeprecated()));
+        assertThat(STICKY, equalTo(methodConfig.getSticky()));
+        assertThat(ONINVOKE, equalTo(methodConfig.getOninvoke()));
+        assertThat(ONTHROW, equalTo(methodConfig.getOnthrow()));
+        assertThat(ONRETURN, equalTo(methodConfig.getOnreturn()));
+        assertThat(CACHE, equalTo(methodConfig.getCache()));
+        assertThat(VALIDATION, equalTo(methodConfig.getValidation()));
+        assertThat(ARGUMENTS_INDEX, equalTo(methodConfig.getArguments().get(0).getIndex().intValue()));
+        assertThat(ARGUMENTS_CALLBACK, equalTo(methodConfig.getArguments().get(0).isCallback()));
+        assertThat(ARGUMENTS_TYPE, equalTo(methodConfig.getArguments().get(0).getType()));
+    }
+
     @Test
     public void testName() throws Exception {
         MethodConfig method = new MethodConfig();
diff --git a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/ReferenceConfigTest.java b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/ReferenceConfigTest.java
index 7c0c7597776..8a5cf100ea6 100644
--- a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/ReferenceConfigTest.java
+++ b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/ReferenceConfigTest.java
@@ -17,6 +17,9 @@
 package org.apache.dubbo.config;
 
 import org.apache.dubbo.common.Constants;
+import org.apache.dubbo.config.annotation.Argument;
+import org.apache.dubbo.config.annotation.Method;
+import org.apache.dubbo.config.annotation.Reference;
 import org.apache.dubbo.config.api.DemoService;
 import org.apache.dubbo.config.context.ConfigManager;
 import org.apache.dubbo.config.provider.impl.DemoServiceImpl;
@@ -124,4 +127,32 @@ public void testReferenceRetry() {
         Assertions.assertNotNull(demoService);
 
     }
+
+    @Test
+    public void testConstructWithReferenceAnnotation() throws NoSuchFieldException {
+        Reference reference = getClass().getDeclaredField("innerTest").getAnnotation(Reference.class);
+        ReferenceConfig referenceConfig = new ReferenceConfig(reference);
+        Assertions.assertTrue(referenceConfig.getMethods().size() == 1);
+        Assertions.assertEquals(((MethodConfig) referenceConfig.getMethods().get(0)).getName(), "sayHello");
+        Assertions.assertTrue(((MethodConfig) referenceConfig.getMethods().get(0)).getTimeout() == 1300);
+        Assertions.assertTrue(((MethodConfig) referenceConfig.getMethods().get(0)).getRetries() == 4);
+        Assertions.assertEquals(((MethodConfig) referenceConfig.getMethods().get(0)).getLoadbalance(), "random");
+        Assertions.assertTrue(((MethodConfig) referenceConfig.getMethods().get(0)).getActives() == 3);
+        Assertions.assertTrue(((MethodConfig) referenceConfig.getMethods().get(0)).getExecutes() == 5);
+        Assertions.assertTrue(((MethodConfig) referenceConfig.getMethods().get(0)).isAsync());
+        Assertions.assertEquals(((MethodConfig) referenceConfig.getMethods().get(0)).getOninvoke(), "i");
+        Assertions.assertEquals(((MethodConfig) referenceConfig.getMethods().get(0)).getOnreturn(), "r");
+        Assertions.assertEquals(((MethodConfig) referenceConfig.getMethods().get(0)).getOnthrow(), "t");
+        Assertions.assertEquals(((MethodConfig) referenceConfig.getMethods().get(0)).getCache(), "c");
+    }
+
+
+    @Reference(methods = {@Method(name = "sayHello", timeout = 1300, retries = 4, loadbalance = "random", async = true,
+            actives = 3, executes = 5, deprecated = true, sticky = true, oninvoke = "i", onthrow = "t", onreturn = "r", cache = "c", validation = "v",
+            arguments = {@Argument(index = 24, callback = true, type = "sss")})})
+    private InnerTest innerTest;
+
+    private class InnerTest {
+
+    }
 }
diff --git a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/beans/factory/annotation/ReferenceBeanBuilder.java b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/beans/factory/annotation/ReferenceBeanBuilder.java
index aff3ed2a5d0..d4aef6a37ec 100644
--- a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/beans/factory/annotation/ReferenceBeanBuilder.java
+++ b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/beans/factory/annotation/ReferenceBeanBuilder.java
@@ -18,6 +18,8 @@
 
 import org.apache.dubbo.common.utils.CollectionUtils;
 import org.apache.dubbo.config.ConsumerConfig;
+import org.apache.dubbo.config.MethodConfig;
+import org.apache.dubbo.config.annotation.Method;
 import org.apache.dubbo.config.annotation.Reference;
 import org.apache.dubbo.config.spring.ReferenceBean;
 
@@ -29,6 +31,7 @@
 import org.springframework.validation.DataBinder;
 
 import java.beans.PropertyEditorSupport;
+import java.util.List;
 import java.util.Map;
 
 import static org.apache.dubbo.config.spring.util.BeanFactoryUtils.getOptionalBean;
@@ -89,6 +92,14 @@ private void configureConsumerConfig(Reference reference, ReferenceBean<?> refer
 
     }
 
+    void configureMethodConfig(Reference reference, ReferenceBean<?> referenceBean){
+        Method[] methods = reference.methods();
+        List<MethodConfig> methodConfigs = MethodConfig.constructMethodConfig(methods);
+        if(!methodConfigs.isEmpty()){
+            referenceBean.setMethods(methodConfigs);
+        }
+    }
+
     @Override
     protected ReferenceBean doBuild() {
         return new ReferenceBean<Object>();
@@ -154,6 +165,8 @@ protected void postConfigureBean(Reference annotation, ReferenceBean bean) throw
 
         configureConsumerConfig(annotation, bean);
 
+        configureMethodConfig(annotation, bean);
+
         bean.afterPropertiesSet();
 
     }
diff --git a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/beans/factory/annotation/ServiceAnnotationBeanPostProcessor.java b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/beans/factory/annotation/ServiceAnnotationBeanPostProcessor.java
index bc5339b55dc..22fa70422d5 100644
--- a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/beans/factory/annotation/ServiceAnnotationBeanPostProcessor.java
+++ b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/beans/factory/annotation/ServiceAnnotationBeanPostProcessor.java
@@ -18,6 +18,7 @@
 
 import org.apache.dubbo.common.logger.Logger;
 import org.apache.dubbo.common.logger.LoggerFactory;
+import org.apache.dubbo.config.MethodConfig;
 import org.apache.dubbo.config.annotation.Service;
 import org.apache.dubbo.config.spring.ServiceBean;
 import org.apache.dubbo.config.spring.context.annotation.DubboClassPathBeanDefinitionScanner;
@@ -434,6 +435,11 @@ private AbstractBeanDefinition buildServiceBeanDefinition(Service service, Class
             builder.addPropertyValue("protocols", protocolRuntimeBeanReferences);
         }
 
+        List<MethodConfig> methodConfigs = MethodConfig.constructMethodConfig(service.methods());
+        if (!methodConfigs.isEmpty()) {
+            builder.addPropertyValue("methods", methodConfigs);
+        }
+
         return builder.getBeanDefinition();
 
     }
@@ -484,4 +490,4 @@ public void setBeanClassLoader(ClassLoader classLoader) {
         this.classLoader = classLoader;
     }
 
-}
\ No newline at end of file
+}
diff --git a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/util/AnnotationUtils.java b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/util/AnnotationUtils.java
index ed2a607bffe..9832e105624 100644
--- a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/util/AnnotationUtils.java
+++ b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/util/AnnotationUtils.java
@@ -258,6 +258,17 @@ public static Map<String, Object> getAttributes(Annotation annotation, PropertyR
                 continue;
             }
 
+            /**
+             * @since 2.7.1
+             * ignore annotation member
+             */
+            if (attributeValue.getClass().isAnnotation()){
+                continue;
+            }
+            if (attributeValue.getClass().isArray() && attributeValue.getClass().getComponentType().isAnnotation()){
+                continue;
+            }
+
             if (attributeValue instanceof String) {
                 attributeValue = resolvePlaceholders(valueOf(attributeValue), propertyResolver);
             } else if (attributeValue instanceof String[]) {
@@ -281,4 +292,4 @@ private static String resolvePlaceholders(String attributeValue, PropertyResolve
         return resolvedValue;
     }
 
-}
\ No newline at end of file
+}
diff --git a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/annotation/consumer/AnnotationAction.java b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/annotation/consumer/AnnotationAction.java
index 35d94fecf04..1e71f01bb01 100644
--- a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/annotation/consumer/AnnotationAction.java
+++ b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/annotation/consumer/AnnotationAction.java
@@ -16,6 +16,7 @@
  */
 package org.apache.dubbo.config.spring.annotation.consumer;
 
+import org.apache.dubbo.config.annotation.Method;
 import org.apache.dubbo.config.annotation.Reference;
 import org.apache.dubbo.config.spring.api.DemoService;
 
@@ -27,11 +28,11 @@
 @Controller("annotationAction")
 public class AnnotationAction {
 
-    @Reference(version = "1.2")
+    @Reference(version = "1.2", methods = {@Method(name = "sayHello", timeout = 5000)})
     private DemoService demoService;
 
     public String doSayName(String name) {
         return demoService.sayName(name);
     }
 
-}
\ No newline at end of file
+}

From feaa9cc073c5f6db36b98ae83fab96037ad82a82 Mon Sep 17 00:00:00 2001
From: cvictory <shenglicao2@gmail.com>
Date: Tue, 12 Mar 2019 18:32:00 +0800
Subject: [PATCH 4/5] #2045 add empty check

---
 .../org/apache/dubbo/config/MethodConfig.java | 25 ++++++++++++++++---
 1 file changed, 22 insertions(+), 3 deletions(-)

diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/MethodConfig.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/MethodConfig.java
index b52d7943914..84510418817 100644
--- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/MethodConfig.java
+++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/MethodConfig.java
@@ -125,10 +125,29 @@ public MethodConfig() {
 
     public MethodConfig(Method method) {
         appendAnnotation(Method.class, method);
+
         this.setReturn(method.isReturn());
-        this.setOninvoke(method.oninvoke());
-        this.setOnreturn(method.onreturn());
-        this.setOnthrow(method.onthrow());
+
+        if(!"".equals(method.oninvoke())){
+            this.setOninvoke(method.oninvoke());
+        }
+        if(!"".equals(method.onreturn())){
+            this.setOnreturn(method.onreturn());
+        }
+        if(!"".equals(method.onthrow())){
+            this.setOnthrow(method.onthrow());
+        }
+        //if "" of @Method, then should set to null
+//        if("".equals(this.loadbalance)){
+//            this.setLoadbalance(null);
+//        }
+//        if("".equals(this.cache)){
+//            this.setLoadbalance(null);
+//        }
+//        if("".equals(this.validation)){
+//            this.setValidation(null);
+//        }
+
         if (method.arguments() != null && method.arguments().length != 0) {
             List<ArgumentConfig> argumentConfigs = new ArrayList<ArgumentConfig>(method.arguments().length);
             this.setArguments(argumentConfigs);

From 324d37270455f14cfda058c80ffc4b542294d45b Mon Sep 17 00:00:00 2001
From: cvictory <shenglicao2@gmail.com>
Date: Tue, 12 Mar 2019 18:33:02 +0800
Subject: [PATCH 5/5] #2045 add empty check

---
 .../java/org/apache/dubbo/config/MethodConfig.java     | 10 ----------
 1 file changed, 10 deletions(-)

diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/MethodConfig.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/MethodConfig.java
index 84510418817..c9478d45cae 100644
--- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/MethodConfig.java
+++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/MethodConfig.java
@@ -137,16 +137,6 @@ public MethodConfig(Method method) {
         if(!"".equals(method.onthrow())){
             this.setOnthrow(method.onthrow());
         }
-        //if "" of @Method, then should set to null
-//        if("".equals(this.loadbalance)){
-//            this.setLoadbalance(null);
-//        }
-//        if("".equals(this.cache)){
-//            this.setLoadbalance(null);
-//        }
-//        if("".equals(this.validation)){
-//            this.setValidation(null);
-//        }
 
         if (method.arguments() != null && method.arguments().length != 0) {
             List<ArgumentConfig> argumentConfigs = new ArrayList<ArgumentConfig>(method.arguments().length);