You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@shenyu.apache.org by zh...@apache.org on 2022/06/12 08:59:10 UTC

[incubator-shenyu] branch master updated: [ISSUE #3484] springmvc client lossless registration (#3537)

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

zhangzicheng pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-shenyu.git


The following commit(s) were added to refs/heads/master by this push:
     new 7c1c7a5f7 [ISSUE #3484] springmvc client lossless registration (#3537)
7c1c7a5f7 is described below

commit 7c1c7a5f7ece4cb92bb3f1f18d7324ccfc054700
Author: chuang <49...@users.noreply.github.com>
AuthorDate: Sun Jun 12 16:59:05 2022 +0800

    [ISSUE #3484] springmvc client lossless registration (#3537)
---
 ...ssor.java => SpringMvcClientEventListener.java} | 94 +++++++++++-----------
 .../src/main/resources/context/shenyu.xml          |  4 +-
 .../src/main/resources/context/shenyu.xml          |  4 +-
 ...enyuSpringWebSocketClientConfigurationTest.java |  2 +-
 .../ShenyuSpringMvcClientConfiguration.java        | 14 ++--
 .../ShenyuSpringMvcClientConfigurationTest.java    |  6 +-
 6 files changed, 63 insertions(+), 61 deletions(-)

diff --git a/shenyu-client/shenyu-client-http/shenyu-client-springmvc/src/main/java/org/apache/shenyu/client/springmvc/init/SpringMvcClientBeanPostProcessor.java b/shenyu-client/shenyu-client-http/shenyu-client-springmvc/src/main/java/org/apache/shenyu/client/springmvc/init/SpringMvcClientEventListener.java
similarity index 84%
rename from shenyu-client/shenyu-client-http/shenyu-client-springmvc/src/main/java/org/apache/shenyu/client/springmvc/init/SpringMvcClientBeanPostProcessor.java
rename to shenyu-client/shenyu-client-http/shenyu-client-springmvc/src/main/java/org/apache/shenyu/client/springmvc/init/SpringMvcClientEventListener.java
index ebe51f231..360476384 100644
--- a/shenyu-client/shenyu-client-http/shenyu-client-springmvc/src/main/java/org/apache/shenyu/client/springmvc/init/SpringMvcClientBeanPostProcessor.java
+++ b/shenyu-client/shenyu-client-http/shenyu-client-springmvc/src/main/java/org/apache/shenyu/client/springmvc/init/SpringMvcClientEventListener.java
@@ -32,7 +32,8 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.aop.support.AopUtils;
 import org.springframework.beans.BeansException;
-import org.springframework.beans.factory.config.BeanPostProcessor;
+import org.springframework.context.ApplicationListener;
+import org.springframework.context.event.ContextRefreshedEvent;
 import org.springframework.core.annotation.AnnotatedElementUtils;
 import org.springframework.core.annotation.AnnotationUtils;
 import org.springframework.lang.NonNull;
@@ -48,43 +49,44 @@ import org.springframework.web.bind.annotation.RequestMapping;
 import java.lang.annotation.Annotation;
 import java.lang.reflect.Method;
 import java.util.ArrayList;
+import java.util.Map;
 import java.util.List;
 import java.util.Objects;
 import java.util.Optional;
 import java.util.Properties;
 
 /**
- * The type Shenyu spring mvc client bean post processor.
+ * The type Shenyu spring mvc client event listener.
  */
-public class SpringMvcClientBeanPostProcessor implements BeanPostProcessor {
-    
+public class SpringMvcClientEventListener implements ApplicationListener<ContextRefreshedEvent> {
+
     /**
      * api path separator.
      */
     private static final String PATH_SEPARATOR = "/";
-    
-    private static final Logger LOG = LoggerFactory.getLogger(SpringMvcClientBeanPostProcessor.class);
-    
+
+    private static final Logger LOG = LoggerFactory.getLogger(SpringMvcClientEventListener.class);
+
     private final ShenyuClientRegisterEventPublisher publisher = ShenyuClientRegisterEventPublisher.getInstance();
-    
+
     private final String contextPath;
-    
+
     private final String appName;
-    
+
     private final Boolean isFull;
-    
+
     private final List<Class<? extends Annotation>> mappingAnnotation = new ArrayList<>(7);
-    
+
     private final String[] pathAttributeNames = new String[]{"path", "value"};
-    
+
     /**
-     * Instantiates a new Spring mvc client bean post processor.
+     * Instantiates a new Spring mvc client event listener.
      *
      * @param clientConfig                   the client config
      * @param shenyuClientRegisterRepository the shenyu client register repository
      */
-    public SpringMvcClientBeanPostProcessor(final PropertiesConfig clientConfig,
-                                            final ShenyuClientRegisterRepository shenyuClientRegisterRepository) {
+    public SpringMvcClientEventListener(final PropertiesConfig clientConfig,
+                                        final ShenyuClientRegisterRepository shenyuClientRegisterRepository) {
         Properties props = clientConfig.getProps();
         this.appName = props.getProperty(ShenyuClientConstants.APP_NAME);
         this.contextPath = Optional.ofNullable(props.getProperty(ShenyuClientConstants.CONTEXT_PATH)).map(UriUtils::repairData).orElse("");
@@ -102,24 +104,30 @@ public class SpringMvcClientBeanPostProcessor implements BeanPostProcessor {
         mappingAnnotation.add(RequestMapping.class);
         publisher.start(shenyuClientRegisterRepository);
     }
-    
+
     @Override
-    public Object postProcessAfterInitialization(@NonNull final Object bean, @NonNull final String beanName) throws BeansException {
+    public void onApplicationEvent(final ContextRefreshedEvent event) throws BeansException {
+        // Filter out
+        if (Boolean.TRUE.equals(isFull)) {
+            return;
+        }
+        Map<String, Object> controllerBeans = event.getApplicationContext().getBeansWithAnnotation(Controller.class);
+        for (Map.Entry<String, Object> entry : controllerBeans.entrySet()) {
+            handler(entry.getValue());
+        }
+    }
+
+    private void handler(@NonNull final Object bean) {
         Class<?> clazz = bean.getClass();
         if (AopUtils.isAopProxy(bean)) {
             clazz = AopUtils.getTargetClass(bean);
         }
-        // Filter out is not controller out
-        if (Boolean.TRUE.equals(isFull) || !hasAnnotation(bean.getClass(), Controller.class)) {
-            return bean;
-        }
-        
         final ShenyuSpringMvcClient beanShenyuClient = AnnotatedElementUtils.findMergedAnnotation(clazz, ShenyuSpringMvcClient.class);
         final String superPath = buildApiSuperPath(clazz);
         // Compatible with previous versions
         if (Objects.nonNull(beanShenyuClient) && superPath.contains("*")) {
             publisher.publishEvent(buildMetaDataDTO(beanShenyuClient, pathJoin(contextPath, superPath)));
-            return bean;
+            return;
         }
         final Method[] methods = ReflectionUtils.getUniqueDeclaredMethods(clazz);
         for (Method method : methods) {
@@ -132,14 +140,8 @@ public class SpringMvcClientBeanPostProcessor implements BeanPostProcessor {
                 publisher.publishEvent(buildMetaDataDTO(methodShenyuClient, buildApiPath(method, superPath)));
             }
         }
-        
-        return bean;
     }
-    
-    private <A extends Annotation> boolean hasAnnotation(final @NonNull Class<?> clazz, final @NonNull Class<A> annotationType) {
-        return Objects.nonNull(AnnotationUtils.findAnnotation(clazz, annotationType));
-    }
-    
+
     private String buildApiPath(@NonNull final Method method, @NonNull final String superPath) {
         ShenyuSpringMvcClient shenyuSpringMvcClient = AnnotatedElementUtils.findMergedAnnotation(method, ShenyuSpringMvcClient.class);
         if (Objects.nonNull(shenyuSpringMvcClient) && StringUtils.isNotBlank(shenyuSpringMvcClient.path())) {
@@ -151,7 +153,7 @@ public class SpringMvcClientBeanPostProcessor implements BeanPostProcessor {
         }
         return pathJoin(contextPath, superPath);
     }
-    
+
     private String getPathByMethod(@NonNull final Method method) {
         for (Class<? extends Annotation> mapping : mappingAnnotation) {
             final String pathByAnnotation = getPathByAnnotation(AnnotationUtils.findAnnotation(method, mapping), pathAttributeNames);
@@ -161,7 +163,7 @@ public class SpringMvcClientBeanPostProcessor implements BeanPostProcessor {
         }
         return null;
     }
-    
+
     private String getPathByAnnotation(@Nullable final Annotation annotation, @NonNull final String... pathAttributeName) {
         if (Objects.isNull(annotation)) {
             return null;
@@ -178,7 +180,7 @@ public class SpringMvcClientBeanPostProcessor implements BeanPostProcessor {
         }
         return null;
     }
-    
+
     private String buildApiSuperPath(@NonNull final Class<?> method) {
         ShenyuSpringMvcClient shenyuSpringMvcClient = AnnotatedElementUtils.findMergedAnnotation(method, ShenyuSpringMvcClient.class);
         if (Objects.nonNull(shenyuSpringMvcClient) && StringUtils.isNotBlank(shenyuSpringMvcClient.path())) {
@@ -191,7 +193,7 @@ public class SpringMvcClientBeanPostProcessor implements BeanPostProcessor {
         }
         return "";
     }
-    
+
     private String pathJoin(@NonNull final String... path) {
         StringBuilder result = new StringBuilder(PATH_SEPARATOR);
         for (String p : path) {
@@ -202,18 +204,18 @@ public class SpringMvcClientBeanPostProcessor implements BeanPostProcessor {
         }
         return result.toString();
     }
-    
+
     private MetaDataRegisterDTO buildMetaDataDTO(@NonNull final ShenyuSpringMvcClient shenyuSpringMvcClient, final String path) {
         return MetaDataRegisterDTO.builder()
-                .contextPath(contextPath)
-                .appName(appName)
-                .path(path)
-                .pathDesc(shenyuSpringMvcClient.desc())
-                .rpcType(RpcTypeEnum.HTTP.getName())
-                .enabled(shenyuSpringMvcClient.enabled())
-                .ruleName(StringUtils.defaultIfBlank(shenyuSpringMvcClient.ruleName(), path))
-                .registerMetaData(shenyuSpringMvcClient.registerMetaData())
-                .build();
+            .contextPath(contextPath)
+            .appName(appName)
+            .path(path)
+            .pathDesc(shenyuSpringMvcClient.desc())
+            .rpcType(RpcTypeEnum.HTTP.getName())
+            .enabled(shenyuSpringMvcClient.enabled())
+            .ruleName(StringUtils.defaultIfBlank(shenyuSpringMvcClient.ruleName(), path))
+            .registerMetaData(shenyuSpringMvcClient.registerMetaData())
+            .build();
     }
-    
+
 }
diff --git a/shenyu-examples/shenyu-examples-springmvc-tomcat/src/main/resources/context/shenyu.xml b/shenyu-examples/shenyu-examples-springmvc-tomcat/src/main/resources/context/shenyu.xml
index a073563c4..6b31081f8 100644
--- a/shenyu-examples/shenyu-examples-springmvc-tomcat/src/main/resources/context/shenyu.xml
+++ b/shenyu-examples/shenyu-examples-springmvc-tomcat/src/main/resources/context/shenyu.xml
@@ -47,8 +47,8 @@
         <constructor-arg ref="shenyuRegisterCenterConfig"/>
     </bean>
 
-    <bean id="springMvcClientBeanPostProcessor"
-          class="org.apache.shenyu.client.springmvc.init.SpringMvcClientBeanPostProcessor">
+    <bean id="SpringMvcClientEventListener"
+          class="org.apache.shenyu.client.springmvc.init.SpringMvcClientEventListener">
         <constructor-arg ref="clientPropertiesConfig"/>
         <constructor-arg ref="clientRegisterRepository"/>
     </bean>
diff --git a/shenyu-examples/shenyu-examples-springmvc/src/main/resources/context/shenyu.xml b/shenyu-examples/shenyu-examples-springmvc/src/main/resources/context/shenyu.xml
index 161879207..7583970fa 100644
--- a/shenyu-examples/shenyu-examples-springmvc/src/main/resources/context/shenyu.xml
+++ b/shenyu-examples/shenyu-examples-springmvc/src/main/resources/context/shenyu.xml
@@ -19,8 +19,8 @@
 <beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
-    <bean id="springMvcClientBeanPostProcessor"
-          class="org.apache.shenyu.client.springmvc.init.SpringMvcClientBeanPostProcessor">
+    <bean id="SpringMvcClientEventListener"
+          class="org.apache.shenyu.client.springmvc.init.SpringMvcClientEventListener">
         <constructor-arg ref="clientPropertiesConfig"/>
         <constructor-arg ref="clientRegisterRepository"/>
     </bean>
diff --git a/shenyu-spring-boot-starter/shenyu-spring-boot-starter-client/shenyu-spring-boot-starter-client-spring-websocket/src/test/java/org/apache/shenyu/springboot/starter/client/spring/websocket/ShenyuSpringWebSocketClientConfigurationTest.java b/shenyu-spring-boot-starter/shenyu-spring-boot-starter-client/shenyu-spring-boot-starter-client-spring-websocket/src/test/java/org/apache/shenyu/springboot/starter/client/spring/websocket/ShenyuSpringWebSocketClientConfigurationTest.java
index a34048e25..8efb3f426 100644
--- a/shenyu-spring-boot-starter/shenyu-spring-boot-starter-client/shenyu-spring-boot-starter-client-spring-websocket/src/test/java/org/apache/shenyu/springboot/starter/client/spring/websocket/ShenyuSpringWebSocketClientConfigurationTest.java
+++ b/shenyu-spring-boot-starter/shenyu-spring-boot-starter-client/shenyu-spring-boot-starter-client-spring-websocket/src/test/java/org/apache/shenyu/springboot/starter/client/spring/websocket/ShenyuSpringWebSocketClientConfigurationTest.java
@@ -60,7 +60,7 @@ public class ShenyuSpringWebSocketClientConfigurationTest {
     }
 
     @Test
-    public void testSpringMvcClientBeanPostProcessor() {
+    public void testSpringWebSocketClientBeanPostProcessor() {
         MockedStatic<RegisterUtils> registerUtilsMockedStatic = mockStatic(RegisterUtils.class);
         registerUtilsMockedStatic.when(() -> RegisterUtils.doLogin(any(), any(), any())).thenReturn(Optional.ofNullable("token"));
         applicationContextRunner.run(context -> {
diff --git a/shenyu-spring-boot-starter/shenyu-spring-boot-starter-client/shenyu-spring-boot-starter-client-springmvc/src/main/java/org/apache/shenyu/springboot/starter/client/springmvc/ShenyuSpringMvcClientConfiguration.java b/shenyu-spring-boot-starter/shenyu-spring-boot-starter-client/shenyu-spring-boot-starter-client-springmvc/src/main/java/org/apache/shenyu/springboot/starter/client/springmvc/ShenyuSpringMvcClientConfiguration.java
index b7d368bda..4f93b63fc 100644
--- a/shenyu-spring-boot-starter/shenyu-spring-boot-starter-client/shenyu-spring-boot-starter-client-springmvc/src/main/java/org/apache/shenyu/springboot/starter/client/springmvc/ShenyuSpringMvcClientConfiguration.java
+++ b/shenyu-spring-boot-starter/shenyu-spring-boot-starter-client/shenyu-spring-boot-starter-client-springmvc/src/main/java/org/apache/shenyu/springboot/starter/client/springmvc/ShenyuSpringMvcClientConfiguration.java
@@ -18,7 +18,7 @@
 package org.apache.shenyu.springboot.starter.client.springmvc;
 
 import org.apache.shenyu.client.springmvc.init.ContextRegisterListener;
-import org.apache.shenyu.client.springmvc.init.SpringMvcClientBeanPostProcessor;
+import org.apache.shenyu.client.springmvc.init.SpringMvcClientEventListener;
 import org.apache.shenyu.common.enums.RpcTypeEnum;
 import org.apache.shenyu.register.client.api.ShenyuClientRegisterRepository;
 import org.apache.shenyu.register.common.config.ShenyuClientConfig;
@@ -33,20 +33,20 @@ import org.springframework.context.annotation.Configuration;
 @Configuration
 @ImportAutoConfiguration(ShenyuClientCommonBeanConfiguration.class)
 public class ShenyuSpringMvcClientConfiguration {
-    
+
     /**
      * Spring mvc client bean post processor.
      *
-     * @param clientConfig the client config
+     * @param clientConfig                   the client config
      * @param shenyuClientRegisterRepository the shenyu client register repository
      * @return the spring mvc client bean post processor
      */
     @Bean
-    public SpringMvcClientBeanPostProcessor springHttpClientBeanPostProcessor(final ShenyuClientConfig clientConfig,
-                                                                              final ShenyuClientRegisterRepository shenyuClientRegisterRepository) {
-        return new SpringMvcClientBeanPostProcessor(clientConfig.getClient().get(RpcTypeEnum.HTTP.getName()), shenyuClientRegisterRepository);
+    public SpringMvcClientEventListener springHttpClientEventListener(final ShenyuClientConfig clientConfig,
+                                                                          final ShenyuClientRegisterRepository shenyuClientRegisterRepository) {
+        return new SpringMvcClientEventListener(clientConfig.getClient().get(RpcTypeEnum.HTTP.getName()), shenyuClientRegisterRepository);
     }
-    
+
     /**
      * Context register listener.
      *
diff --git a/shenyu-spring-boot-starter/shenyu-spring-boot-starter-client/shenyu-spring-boot-starter-client-springmvc/src/test/java/org/apache/shenyu/springboot/starter/client/springmvc/ShenyuSpringMvcClientConfigurationTest.java b/shenyu-spring-boot-starter/shenyu-spring-boot-starter-client/shenyu-spring-boot-starter-client-springmvc/src/test/java/org/apache/shenyu/springboot/starter/client/springmvc/ShenyuSpringMvcClientConfigurationTest.java
index 6f5c4ecef..d2a517f10 100644
--- a/shenyu-spring-boot-starter/shenyu-spring-boot-starter-client/shenyu-spring-boot-starter-client-springmvc/src/test/java/org/apache/shenyu/springboot/starter/client/springmvc/ShenyuSpringMvcClientConfigurationTest.java
+++ b/shenyu-spring-boot-starter/shenyu-spring-boot-starter-client/shenyu-spring-boot-starter-client-springmvc/src/test/java/org/apache/shenyu/springboot/starter/client/springmvc/ShenyuSpringMvcClientConfigurationTest.java
@@ -18,7 +18,7 @@
 package org.apache.shenyu.springboot.starter.client.springmvc;
 
 import org.apache.shenyu.client.springmvc.init.ContextRegisterListener;
-import org.apache.shenyu.client.springmvc.init.SpringMvcClientBeanPostProcessor;
+import org.apache.shenyu.client.springmvc.init.SpringMvcClientEventListener;
 import org.apache.shenyu.register.client.http.utils.RegisterUtils;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
@@ -61,11 +61,11 @@ public class ShenyuSpringMvcClientConfigurationTest {
     }
 
     @Test
-    public void testSpringMvcClientBeanPostProcessor() {
+    public void testSpringMvcClientEventListener() {
         MockedStatic<RegisterUtils> registerUtilsMockedStatic = mockStatic(RegisterUtils.class);
         registerUtilsMockedStatic.when(() -> RegisterUtils.doLogin(any(), any(), any())).thenReturn(Optional.ofNullable("token"));
         applicationContextRunner.run(context -> {
-            SpringMvcClientBeanPostProcessor processor = context.getBean("springHttpClientBeanPostProcessor", SpringMvcClientBeanPostProcessor.class);
+            SpringMvcClientEventListener processor = context.getBean("springHttpClientEventListener", SpringMvcClientEventListener.class);
             assertNotNull(processor);
         });
         registerUtilsMockedStatic.close();