You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@eventmesh.apache.org by jo...@apache.org on 2023/02/12 08:01:21 UTC

[incubator-eventmesh] branch master updated: [ISSUE #3116]Refactor ExtensionClassLoader implement (#3117)

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

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


The following commit(s) were added to refs/heads/master by this push:
     new c1158f693 [ISSUE #3116]Refactor ExtensionClassLoader implement (#3117)
c1158f693 is described below

commit c1158f69355602b7d98c85c814dcbb10d80bd744
Author: mxsm <lj...@gmail.com>
AuthorDate: Sun Feb 12 16:01:16 2023 +0800

    [ISSUE #3116]Refactor ExtensionClassLoader implement (#3117)
    
    * [ISSUE #3116]Refactor ExtensionClassLoader implement
    
    * polish code
---
 eventmesh-spi/build.gradle                         |  5 +-
 .../eventmesh/spi/EventMeshExtensionFactory.java   | 44 ++++++++---------
 .../spi/loader/EventMeshUrlClassLoader.java        | 10 ++--
 .../spi/loader/JarExtensionClassLoader.java        | 57 ++++++++++------------
 .../spi/loader/MetaInfExtensionClassLoader.java    | 28 +++++++----
 .../spi/EventMeshExtensionFactoryTest.java         | 24 ++++++++-
 6 files changed, 100 insertions(+), 68 deletions(-)

diff --git a/eventmesh-spi/build.gradle b/eventmesh-spi/build.gradle
index 4980522b4..8b6fcbd8f 100644
--- a/eventmesh-spi/build.gradle
+++ b/eventmesh-spi/build.gradle
@@ -18,4 +18,7 @@ dependencies {
     implementation project(":eventmesh-common")
     implementation "org.apache.commons:commons-collections4"
     testImplementation project(":eventmesh-common")
-}
\ No newline at end of file
+
+    compileOnly 'org.projectlombok:lombok'
+    annotationProcessor 'org.projectlombok:lombok'
+}
diff --git a/eventmesh-spi/src/main/java/org/apache/eventmesh/spi/EventMeshExtensionFactory.java b/eventmesh-spi/src/main/java/org/apache/eventmesh/spi/EventMeshExtensionFactory.java
index 6de216b40..c000a0841 100644
--- a/eventmesh-spi/src/main/java/org/apache/eventmesh/spi/EventMeshExtensionFactory.java
+++ b/eventmesh-spi/src/main/java/org/apache/eventmesh/spi/EventMeshExtensionFactory.java
@@ -35,26 +35,26 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 /**
- * The extension fetching factory, all extension plugins should be fetched by this factory.
- * And all the extension plugins defined in eventmesh should have {@link EventMeshSPI} annotation.
+ * The extension fetching factory, all extension plugins should be fetched by this factory. And all the extension plugins defined in eventmesh should
+ * have {@link EventMeshSPI} annotation.
  */
 public class EventMeshExtensionFactory {
 
-    private EventMeshExtensionFactory() {
-
-    }
-
     private static final Logger logger = LoggerFactory.getLogger(EventMeshExtensionFactory.class);
 
-    private static final List<ExtensionClassLoader> extensionClassLoaders = new ArrayList<>();
+    private static final List<ExtensionClassLoader> EXTENSION_CLASS_LOADERS = new ArrayList<>();
+
+    private static final ConcurrentHashMap<String, Object> EXTENSION_INSTANCE_CACHE = new ConcurrentHashMap<>(16);
 
     static {
-        extensionClassLoaders.add(new MetaInfExtensionClassLoader());
-        extensionClassLoaders.add(new JarExtensionClassLoader());
+        EXTENSION_CLASS_LOADERS.add(MetaInfExtensionClassLoader.getInstance());
+        EXTENSION_CLASS_LOADERS.add(JarExtensionClassLoader.getInstance());
     }
 
-    private static final ConcurrentHashMap<String, Object> EXTENSION_INSTANCE_CACHE =
-        new ConcurrentHashMap<>(16);
+
+    private EventMeshExtensionFactory() {
+
+    }
 
     /**
      * @param extensionType extension plugin class type
@@ -83,21 +83,21 @@ public class EventMeshExtensionFactory {
     private static <T> T getSingletonExtension(Class<T> extensionType, String extensionInstanceName) {
         return (T) EXTENSION_INSTANCE_CACHE.computeIfAbsent(extensionInstanceName, name -> {
             Class<T> extensionInstanceClass = getExtensionInstanceClass(extensionType, extensionInstanceName);
+            if (extensionInstanceClass == null) {
+                return null;
+            }
             try {
-                if (extensionInstanceClass == null) {
-                    return null;
-                }
                 T extensionInstance = extensionInstanceClass.getDeclaredConstructor().newInstance();
                 ConfigService.getInstance().populateConfigForObject(extensionInstance);
 
                 logger.info("initialize extension instance success, extensionType: {}, extensionInstanceName: {}",
-                        extensionType, extensionInstanceName);
+                    extensionType, extensionInstanceName);
                 return extensionInstance;
             } catch (NoSuchMethodException | InstantiationException | IllegalAccessException | InvocationTargetException e) {
                 throw new ExtensionException("Extension initialize error", e);
             } catch (NoSuchFieldException | IOException e) {
                 logger.error("initialize extension instance config failed, extensionType: {}, extensionInstanceName: {}",
-                        extensionType, extensionInstanceName, e);
+                    extensionType, extensionInstanceName, e);
                 throw new ExtensionException("Extension initialize error", e);
             }
         });
@@ -105,28 +105,28 @@ public class EventMeshExtensionFactory {
 
     private static <T> T getPrototypeExtension(Class<T> extensionType, String extensionInstanceName) {
         Class<T> extensionInstanceClass = getExtensionInstanceClass(extensionType, extensionInstanceName);
+        if (extensionInstanceClass == null) {
+            return null;
+        }
         try {
-            if (extensionInstanceClass == null) {
-                return null;
-            }
             T extensionInstance = extensionInstanceClass.getDeclaredConstructor().newInstance();
             ConfigService.getInstance().populateConfigForObject(extensionInstance);
 
             logger.info("initialize extension instance success, extensionType: {}, extensionName: {}",
-                    extensionType, extensionInstanceName);
+                extensionType, extensionInstanceName);
             return extensionInstance;
         } catch (NoSuchMethodException | InstantiationException | IllegalAccessException | InvocationTargetException e) {
             throw new ExtensionException("Extension initialize error", e);
         } catch (NoSuchFieldException | IOException e) {
             logger.error("initialize extension instance config failed, extensionType: {}, extensionInstanceName: {}",
-                    extensionType, extensionInstanceName, e);
+                extensionType, extensionInstanceName, e);
             throw new ExtensionException("Extension initialize error", e);
         }
     }
 
     @SuppressWarnings("unchecked")
     private static <T> Class<T> getExtensionInstanceClass(Class<T> extensionType, String extensionInstanceName) {
-        for (ExtensionClassLoader extensionClassLoader : extensionClassLoaders) {
+        for (ExtensionClassLoader extensionClassLoader : EXTENSION_CLASS_LOADERS) {
             Map<String, Class<?>> extensionInstanceClassMap = extensionClassLoader.loadExtensionClass(extensionType, extensionInstanceName);
             Class<?> instanceClass = extensionInstanceClassMap.get(extensionInstanceName);
             if (instanceClass != null) {
diff --git a/eventmesh-spi/src/main/java/org/apache/eventmesh/spi/loader/EventMeshUrlClassLoader.java b/eventmesh-spi/src/main/java/org/apache/eventmesh/spi/loader/EventMeshUrlClassLoader.java
index 9a27d495e..713e5ac12 100644
--- a/eventmesh-spi/src/main/java/org/apache/eventmesh/spi/loader/EventMeshUrlClassLoader.java
+++ b/eventmesh-spi/src/main/java/org/apache/eventmesh/spi/loader/EventMeshUrlClassLoader.java
@@ -26,15 +26,13 @@ import java.util.List;
 public class EventMeshUrlClassLoader extends URLClassLoader {
 
     public static EventMeshUrlClassLoader getInstance() {
-        return EventMeshUrlClassLoaderHolder.instance;
+        return EventMeshUrlClassLoaderHolder.INSTANCE;
     }
 
     /**
      * Appends the specified URL to the list of URLs to search for classes and resources.
      * <p>
-     * If the URL specified is {@code null} or is already in the
-     * list of URLs, or if this loader is closed, then invoking this
-     * method has no effect.
+     * If the URL specified is {@code null} or is already in the list of URLs, or if this loader is closed, then invoking this method has no effect.
      * <p>
      * More detail see {@link URLClassLoader#addURL(URL)}
      *
@@ -52,6 +50,8 @@ public class EventMeshUrlClassLoader extends URLClassLoader {
     }
 
     private static class EventMeshUrlClassLoaderHolder {
-        private static EventMeshUrlClassLoader instance = new EventMeshUrlClassLoader(new URL[0], Thread.currentThread().getContextClassLoader());
+
+        private static final EventMeshUrlClassLoader INSTANCE = new EventMeshUrlClassLoader(new URL[0],
+            Thread.currentThread().getContextClassLoader());
     }
 }
diff --git a/eventmesh-spi/src/main/java/org/apache/eventmesh/spi/loader/JarExtensionClassLoader.java b/eventmesh-spi/src/main/java/org/apache/eventmesh/spi/loader/JarExtensionClassLoader.java
index 8c7d883f1..e237b992a 100644
--- a/eventmesh-spi/src/main/java/org/apache/eventmesh/spi/loader/JarExtensionClassLoader.java
+++ b/eventmesh-spi/src/main/java/org/apache/eventmesh/spi/loader/JarExtensionClassLoader.java
@@ -41,42 +41,44 @@ import org.slf4j.LoggerFactory;
 import com.google.common.base.Joiner;
 import com.google.common.collect.Lists;
 
+import lombok.extern.slf4j.Slf4j;
+
 /**
  * Load extension from '${eventMeshPluginDir}', the default loading directory is './plugin'
  */
+@Slf4j
 public class JarExtensionClassLoader implements ExtensionClassLoader {
 
-    private static final Logger logger = LoggerFactory.getLogger(JarExtensionClassLoader.class);
-
     private static final String EVENT_MESH_PLUGIN_DIR = "eventMeshPluginDir";
 
-    private static final ConcurrentHashMap<Class<?>, Map<String, Class<?>>> EXTENSION_CLASS_CACHE =
-            new ConcurrentHashMap<>(16);
+    private static final String EVENTMESH_EXTENSION_PLUGIN_DIR = System.getProperty(EVENT_MESH_PLUGIN_DIR,
+        Joiner.on(File.separator).join(Lists.newArrayList(".", "plugin")));
+
+    private static final JarExtensionClassLoader INSTANCE = new JarExtensionClassLoader();
+
+    private final ConcurrentHashMap<Class<?>, Map<String, Class<?>>> extensionClassCache = new ConcurrentHashMap<>(16);
 
-    private static final String EVENTMESH_EXTENSION_PLUGIN_DIR =
-            System.getProperty(EVENT_MESH_PLUGIN_DIR,
-                    Joiner.on(File.separator).join(Lists.newArrayList(".", "plugin")));
+    private JarExtensionClassLoader() {
+
+    }
+
+    public static JarExtensionClassLoader getInstance() {
+        return INSTANCE;
+    }
 
     @Override
-    public <T> Map<String, Class<?>> loadExtensionClass(Class<T> extensionType,
-                                                        String extensionInstanceName) {
-        return EXTENSION_CLASS_CACHE
-                .computeIfAbsent(extensionType, t -> doLoadExtensionClass(t, extensionInstanceName));
+    public <T> Map<String, Class<?>> loadExtensionClass(Class<T> extensionType, String extensionInstanceName) {
+        return extensionClassCache.computeIfAbsent(extensionType, t -> doLoadExtensionClass(t, extensionInstanceName));
     }
 
-    private <T> Map<String, Class<?>> doLoadExtensionClass(Class<T> extensionType,
-                                                           String extensionInstanceName) {
+    private <T> Map<String, Class<?>> doLoadExtensionClass(Class<T> extensionType, String extensionInstanceName) {
         Map<String, Class<?>> extensionMap = new HashMap<>(16);
         EventMeshSPI eventMeshSpiAnnotation = extensionType.getAnnotation(EventMeshSPI.class);
 
-        String pluginDir = Paths.get(
-                EVENTMESH_EXTENSION_PLUGIN_DIR,
-                eventMeshSpiAnnotation.eventMeshExtensionType().getExtensionTypeName(),
-                extensionInstanceName
-        ).toString();
+        String pluginDir = Paths.get(EVENTMESH_EXTENSION_PLUGIN_DIR, eventMeshSpiAnnotation.eventMeshExtensionType().getExtensionTypeName(),
+            extensionInstanceName).toString();
 
-        String extensionFileName =
-                EventMeshExtensionConstant.EVENTMESH_EXTENSION_META_DIR + extensionType.getName();
+        String extensionFileName = EventMeshExtensionConstant.EVENTMESH_EXTENSION_META_DIR + extensionType.getName();
         EventMeshUrlClassLoader urlClassLoader = EventMeshUrlClassLoader.getInstance();
         urlClassLoader.addUrls(loadJarPathFromResource(pluginDir));
         try {
@@ -96,7 +98,7 @@ public class JarExtensionClassLoader implements ExtensionClassLoader {
     private List<URL> loadJarPathFromResource(String pluginPath) {
         File plugin = new File(pluginPath);
         if (!plugin.exists()) {
-            logger.warn("plugin dir:{} is not exist", pluginPath);
+            log.warn("plugin dir:{} is not exist", pluginPath);
             return Lists.newArrayList();
         }
         if (plugin.isFile() && plugin.getName().endsWith(".jar")) {
@@ -113,15 +115,13 @@ public class JarExtensionClassLoader implements ExtensionClassLoader {
                 pluginUrls.addAll(loadJarPathFromResource(file.getPath()));
             }
         }
-        // TODO: Sort the path here just to guarantee load the ConsumeMessageConcurrentlyService
+        //  Sort the path here just to guarantee load the ConsumeMessageConcurrentlyService
         //  defined in EventMesh rather than defined in rocketmq
         pluginUrls.sort(Comparator.comparing(URL::getPath));
         return pluginUrls;
     }
 
-    private static <T> Map<String, Class<?>> loadResources(URLClassLoader urlClassLoader, URL url,
-                                                           Class<T> extensionType)
-            throws IOException {
+    private <T> Map<String, Class<?>> loadResources(URLClassLoader urlClassLoader, URL url, Class<T> extensionType) throws IOException {
         Map<String, Class<?>> extensionMap = new HashMap<>();
         try (InputStream inputStream = url.openStream()) {
             Properties properties = new Properties();
@@ -131,13 +131,10 @@ public class JarExtensionClassLoader implements ExtensionClassLoader {
                 String extensionClassStr = (String) extensionClass;
                 try {
                     Class<?> targetClass = urlClassLoader.loadClass(extensionClassStr);
-                    logger
-                            .info("load extension class success, extensionType: {}, extensionClass: {}",
-                                    extensionType, targetClass);
+                    log.info("load extension class success, extensionType: {}, extensionClass: {}", extensionType, targetClass);
                     if (!extensionType.isAssignableFrom(targetClass)) {
                         throw new ExtensionException(
-                                String.format("class: %s is not subClass of %s", targetClass,
-                                        extensionType));
+                            String.format("class: %s is not subClass of %s", targetClass, extensionType));
                     }
                     extensionMap.put(extensionNameStr, targetClass);
                 } catch (ClassNotFoundException e) {
diff --git a/eventmesh-spi/src/main/java/org/apache/eventmesh/spi/loader/MetaInfExtensionClassLoader.java b/eventmesh-spi/src/main/java/org/apache/eventmesh/spi/loader/MetaInfExtensionClassLoader.java
index 8e6cc8a56..2333117a3 100644
--- a/eventmesh-spi/src/main/java/org/apache/eventmesh/spi/loader/MetaInfExtensionClassLoader.java
+++ b/eventmesh-spi/src/main/java/org/apache/eventmesh/spi/loader/MetaInfExtensionClassLoader.java
@@ -31,19 +31,31 @@ import java.util.concurrent.ConcurrentHashMap;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+
+import lombok.extern.slf4j.Slf4j;
+
 /**
  * Load extension from classpath
  */
+
+@Slf4j
 public class MetaInfExtensionClassLoader implements ExtensionClassLoader {
 
-    private static final Logger logger = LoggerFactory.getLogger(MetaInfExtensionClassLoader.class);
+    private static final MetaInfExtensionClassLoader INSTANCE = new MetaInfExtensionClassLoader();
+
+    private final ConcurrentHashMap<Class<?>, Map<String, Class<?>>> extensionClassCache = new ConcurrentHashMap<>(16);
 
-    private static final ConcurrentHashMap<Class<?>, Map<String, Class<?>>> EXTENSION_CLASS_CACHE =
-            new ConcurrentHashMap<>(16);
+    private MetaInfExtensionClassLoader() {
+
+    }
 
     @Override
     public <T> Map<String, Class<?>> loadExtensionClass(Class<T> extensionType, String extensionInstanceName) {
-        return EXTENSION_CLASS_CACHE.computeIfAbsent(extensionType, this::doLoadExtensionClass);
+        return extensionClassCache.computeIfAbsent(extensionType, this::doLoadExtensionClass);
+    }
+
+    public static MetaInfExtensionClassLoader getInstance() {
+        return INSTANCE;
     }
 
     private <T> Map<String, Class<?>> doLoadExtensionClass(Class<T> extensionType) {
@@ -64,7 +76,7 @@ public class MetaInfExtensionClassLoader implements ExtensionClassLoader {
         return extensionMap;
     }
 
-    private static <T> Map<String, Class<?>> loadResources(URL url, Class<T> extensionType) throws IOException {
+    private <T> Map<String, Class<?>> loadResources(URL url, Class<T> extensionType) throws IOException {
         Map<String, Class<?>> extensionMap = new HashMap<>();
         try (InputStream inputStream = url.openStream()) {
             Properties properties = new Properties();
@@ -74,11 +86,9 @@ public class MetaInfExtensionClassLoader implements ExtensionClassLoader {
                 String extensionClassStr = (String) extensionClass;
                 try {
                     Class<?> targetClass = Class.forName(extensionClassStr);
-                    logger.info("load extension class success, extensionType: {}, extensionClass: {}",
-                            extensionType, targetClass);
+                    log.info("load extension class success, extensionType: {}, extensionClass: {}", extensionType, targetClass);
                     if (!extensionType.isAssignableFrom(targetClass)) {
-                        throw new ExtensionException(
-                                String.format("class: %s is not subClass of %s", targetClass, extensionType));
+                        throw new ExtensionException(String.format("class: %s is not subClass of %s", targetClass, extensionType));
                     }
                     extensionMap.put(extensionNameStr, targetClass);
                 } catch (ClassNotFoundException e) {
diff --git a/eventmesh-spi/src/test/java/org/apache/eventmesh/spi/EventMeshExtensionFactoryTest.java b/eventmesh-spi/src/test/java/org/apache/eventmesh/spi/EventMeshExtensionFactoryTest.java
index 5dc24c592..55b3156c7 100644
--- a/eventmesh-spi/src/test/java/org/apache/eventmesh/spi/EventMeshExtensionFactoryTest.java
+++ b/eventmesh-spi/src/test/java/org/apache/eventmesh/spi/EventMeshExtensionFactoryTest.java
@@ -38,4 +38,26 @@ public class EventMeshExtensionFactoryTest {
         TestPrototypeExtension prototypeExtensionB = EventMeshExtensionFactory.getExtension(TestPrototypeExtension.class, "prototypeExtension");
         Assert.assertNotSame(prototypeExtensionA, prototypeExtensionB);
     }
-}
\ No newline at end of file
+
+    @Test
+    public void testGetExtension() {
+        ExtensionException exception = null;
+        try {
+            EventMeshExtensionFactory.getExtension(null, "eventmesh");
+        } catch (Exception ex) {
+            if (ex instanceof ExtensionException) {
+                exception = (ExtensionException) ex;
+            }
+        }
+        Assert.assertNotNull(exception);
+        exception = null;
+        try {
+            EventMeshExtensionFactory.getExtension(TestPrototypeExtension.class, null);
+        } catch (Exception ex) {
+            if (ex instanceof ExtensionException) {
+                exception = (ExtensionException) ex;
+            }
+        }
+        Assert.assertNotNull(exception);
+    }
+}


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@eventmesh.apache.org
For additional commands, e-mail: commits-help@eventmesh.apache.org