You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@eventmesh.apache.org by ch...@apache.org on 2021/10/03 14:24:28 UTC

[incubator-eventmesh] branch develop updated: [ISSUE #367] Optimize plugin load (#519)

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

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


The following commit(s) were added to refs/heads/develop by this push:
     new 6b7280a  [ISSUE #367] Optimize plugin load (#519)
6b7280a is described below

commit 6b7280aec2bb48286d85bdcaeb7a2a010356e196
Author: Wenjun Ruan <we...@apache.org>
AuthorDate: Sun Oct 3 22:24:19 2021 +0800

    [ISSUE #367] Optimize plugin load (#519)
    
    * 1. Optimize plugin load, support load plugin by plugin instance name
    2. Optimize install plugin, suppory install plugin by ./gradlew jar dist
    3. Make UrlClassLoader siglenton
    
    * add license header
    
    * optimize path
    
    * resolve confilct
---
 .gitignore                                         |  3 +-
 build.gradle                                       | 39 +++++++++++++++
 eventmesh-connector-plugin/build.gradle            | 24 +---------
 .../api/connector/ConnectorResourceService.java    |  3 +-
 .../eventmesh/api/consumer/MeshMQPushConsumer.java |  3 +-
 .../eventmesh/api/producer/MeshMQProducer.java     |  3 +-
 .../rocketmq/consumer/RocketMQConsumerImpl.java    |  9 +---
 .../rocketmq/producer/RocketMQProducerImpl.java    |  6 +--
 eventmesh-registry-plugin/build.gradle             | 21 --------
 .../eventmesh/api/registry/RegistryService.java    |  3 +-
 eventmesh-security-plugin/build.gradle             | 23 +--------
 .../org/apache/eventmesh/api/acl/AclService.java   |  3 +-
 .../eventmesh/spi/EventMeshExtensionFactory.java   | 22 ++++-----
 ...entMeshSPI.java => EventMeshExtensionType.java} | 32 ++++++-------
 .../org/apache/eventmesh/spi/EventMeshSPI.java     |  6 +++
 .../spi/loader/EventMeshUrlClassLoader.java        | 56 ++++++++++++++++++++++
 .../eventmesh/spi/loader/ExtensionClassLoader.java |  9 ++--
 .../spi/loader/JarExtensionClassLoader.java        | 32 ++++++++-----
 .../spi/loader/MetaInfExtensionClassLoader.java    |  4 +-
 .../spi/example/TestPrototypeExtension.java        |  3 +-
 .../spi/example/TestSingletonExtension.java        |  3 +-
 21 files changed, 176 insertions(+), 131 deletions(-)

diff --git a/.gitignore b/.gitignore
index 2f470f5..922026c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -19,4 +19,5 @@ dist
 classes
 package-lock.json
 node_modules
-.DS_Store
\ No newline at end of file
+.DS_Store
+.run
\ No newline at end of file
diff --git a/build.gradle b/build.gradle
index ae7f428..bc7d881 100644
--- a/build.gradle
+++ b/build.gradle
@@ -187,6 +187,22 @@ subprojects {
         }
     }
 
+    // pluginType:
+    //      pluginInstanceName:
+    //            moduleName
+    Map<String, Map<String, String>> pluginTypeMap = [
+            "connector": [
+                    "rocketmq"  : "eventmesh-connector-rocketmq",
+                    "standalone": "eventmesh-connector-standalone",
+            ],
+            "security" : [
+                    "acl": "eventmesh-security-acl",
+            ],
+            "registry" : [
+                    "namesrv": "eventmesh-registry-rocketmq-namesrv",
+            ]
+    ]
+
     task dist(dependsOn: ['jar']) {
         doFirst {
             new File(projectDir, '../dist/bin').mkdirs()
@@ -196,6 +212,29 @@ subprojects {
         }
 
         doLast {
+            pluginTypeMap.forEach((pluginType, pluginInstanceMap) -> {
+                pluginInstanceMap.forEach((pluginInstanceName, moduleName) -> {
+                    if (moduleName == project.name) {
+                        println String.format("install plugin, pluginType: %s, pluginInstanceName: %s, module: %s",
+                                pluginType, pluginInstanceName, moduleName)
+                        new File("${rootDir}/dist/plugin/${pluginType}/${pluginInstanceName}").mkdirs()
+                        copy {
+                            into "${rootDir}/dist/plugin/${pluginType}/${pluginInstanceName}"
+                            from project.jar.getArchivePath()
+                        }
+                        copy {
+                            into "${rootDir}/dist/plugin/${pluginType}/${pluginInstanceName}"
+                            from project.configurations.runtimeClasspath
+                        }
+                        copy {
+                            into "${rootDir}/dist/conf"
+                            from sourceSets.main.resources.srcDirs
+                            exclude 'META-INF'
+                        }
+                    }
+                })
+            })
+
             copy {
                 into('../dist/apps/')
                 from project.jar.getArchivePath()
diff --git a/eventmesh-connector-plugin/build.gradle b/eventmesh-connector-plugin/build.gradle
index 3c4555b..d973dce 100644
--- a/eventmesh-connector-plugin/build.gradle
+++ b/eventmesh-connector-plugin/build.gradle
@@ -13,26 +13,4 @@
  * 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.
- */
-
-task copyConnectorPlugin(dependsOn: ['jar']) {
-    doFirst {
-        new File(projectDir, '../eventmesh-connector-plugin/dist/apps').mkdir()
-        new File(projectDir, '../dist/plugin/connector').mkdirs()
-    }
-    doLast {
-        copy {
-            into('../eventmesh-connector-plugin/dist/apps/')
-            from project.jar.getArchivePath()
-            exclude {
-                "eventmesh-connector-plugin-${version}.jar"
-                "eventmesh-connector-api-${version}.jar"
-            }
-        }
-        copy {
-            into '../dist/plugin/connector'
-            from "../eventmesh-connector-plugin/dist/apps/eventmesh-connector-standalone-${version}.jar"
-            from "../eventmesh-connector-plugin/dist/apps/eventmesh-connector-rocketmq-${version}.jar"
-        }
-    }
-}
\ No newline at end of file
+ */
\ No newline at end of file
diff --git a/eventmesh-connector-plugin/eventmesh-connector-api/src/main/java/org/apache/eventmesh/api/connector/ConnectorResourceService.java b/eventmesh-connector-plugin/eventmesh-connector-api/src/main/java/org/apache/eventmesh/api/connector/ConnectorResourceService.java
index d48f8ce..d701639 100644
--- a/eventmesh-connector-plugin/eventmesh-connector-api/src/main/java/org/apache/eventmesh/api/connector/ConnectorResourceService.java
+++ b/eventmesh-connector-plugin/eventmesh-connector-api/src/main/java/org/apache/eventmesh/api/connector/ConnectorResourceService.java
@@ -16,9 +16,10 @@
  */
 package org.apache.eventmesh.api.connector;
 
+import org.apache.eventmesh.spi.EventMeshExtensionType;
 import org.apache.eventmesh.spi.EventMeshSPI;
 
-@EventMeshSPI(isSingleton = true)
+@EventMeshSPI(isSingleton = true, eventMeshExtensionType = EventMeshExtensionType.CONNECTOR)
 public interface ConnectorResourceService {
 
     /**
diff --git a/eventmesh-connector-plugin/eventmesh-connector-api/src/main/java/org/apache/eventmesh/api/consumer/MeshMQPushConsumer.java b/eventmesh-connector-plugin/eventmesh-connector-api/src/main/java/org/apache/eventmesh/api/consumer/MeshMQPushConsumer.java
index 998fcc1..dcf558b 100644
--- a/eventmesh-connector-plugin/eventmesh-connector-api/src/main/java/org/apache/eventmesh/api/consumer/MeshMQPushConsumer.java
+++ b/eventmesh-connector-plugin/eventmesh-connector-api/src/main/java/org/apache/eventmesh/api/consumer/MeshMQPushConsumer.java
@@ -25,9 +25,10 @@ import io.openmessaging.api.Consumer;
 import io.openmessaging.api.Message;
 
 import org.apache.eventmesh.api.AbstractContext;
+import org.apache.eventmesh.spi.EventMeshExtensionType;
 import org.apache.eventmesh.spi.EventMeshSPI;
 
-@EventMeshSPI(isSingleton = false)
+@EventMeshSPI(isSingleton = false, eventMeshExtensionType = EventMeshExtensionType.CONNECTOR)
 public interface MeshMQPushConsumer extends Consumer {
 
     void init(Properties keyValue) throws Exception;
diff --git a/eventmesh-connector-plugin/eventmesh-connector-api/src/main/java/org/apache/eventmesh/api/producer/MeshMQProducer.java b/eventmesh-connector-plugin/eventmesh-connector-api/src/main/java/org/apache/eventmesh/api/producer/MeshMQProducer.java
index ef0d2f5..d87be7d 100644
--- a/eventmesh-connector-plugin/eventmesh-connector-api/src/main/java/org/apache/eventmesh/api/producer/MeshMQProducer.java
+++ b/eventmesh-connector-plugin/eventmesh-connector-api/src/main/java/org/apache/eventmesh/api/producer/MeshMQProducer.java
@@ -24,9 +24,10 @@ import io.openmessaging.api.Producer;
 import io.openmessaging.api.SendCallback;
 
 import org.apache.eventmesh.api.RRCallback;
+import org.apache.eventmesh.spi.EventMeshExtensionType;
 import org.apache.eventmesh.spi.EventMeshSPI;
 
-@EventMeshSPI(isSingleton = false)
+@EventMeshSPI(isSingleton = false, eventMeshExtensionType = EventMeshExtensionType.CONNECTOR)
 public interface MeshMQProducer extends Producer {
 
     void init(Properties properties) throws Exception;
diff --git a/eventmesh-connector-plugin/eventmesh-connector-rocketmq/src/main/java/org/apache/eventmesh/connector/rocketmq/consumer/RocketMQConsumerImpl.java b/eventmesh-connector-plugin/eventmesh-connector-rocketmq/src/main/java/org/apache/eventmesh/connector/rocketmq/consumer/RocketMQConsumerImpl.java
index 7087739..d885af0 100644
--- a/eventmesh-connector-plugin/eventmesh-connector-rocketmq/src/main/java/org/apache/eventmesh/connector/rocketmq/consumer/RocketMQConsumerImpl.java
+++ b/eventmesh-connector-plugin/eventmesh-connector-rocketmq/src/main/java/org/apache/eventmesh/connector/rocketmq/consumer/RocketMQConsumerImpl.java
@@ -29,11 +29,10 @@ import io.openmessaging.api.Message;
 import io.openmessaging.api.MessageListener;
 import io.openmessaging.api.MessageSelector;
 import io.openmessaging.api.MessagingAccessPoint;
-import io.openmessaging.api.OMS;
-import io.openmessaging.api.OMSBuiltinKeys;
 
 import org.apache.eventmesh.api.AbstractContext;
 import org.apache.eventmesh.api.consumer.MeshMQPushConsumer;
+import org.apache.eventmesh.connector.rocketmq.MessagingAccessPointImpl;
 import org.apache.eventmesh.connector.rocketmq.common.Constants;
 import org.apache.eventmesh.connector.rocketmq.common.EventMeshConstants;
 import org.apache.eventmesh.connector.rocketmq.config.ClientConfiguration;
@@ -53,8 +52,6 @@ public class RocketMQConsumerImpl implements MeshMQPushConsumer {
 
     public Logger messageLogger = LoggerFactory.getLogger("message");
 
-    public final String DEFAULT_ACCESS_DRIVER = "org.apache.eventmesh.connector.rocketmq.MessagingAccessPointImpl";
-
     private PushConsumerImpl pushConsumer;
 
     @Override
@@ -75,9 +72,7 @@ public class RocketMQConsumerImpl implements MeshMQPushConsumer {
         }
 
         String omsNamesrv = clientConfiguration.namesrvAddr;
-//        KeyValue properties = OMS.newKeyValue().put(OMSBuiltinKeys.DRIVER_IMPL, DEFAULT_ACCESS_DRIVER);
         Properties properties = new Properties();
-        properties.put(OMSBuiltinKeys.DRIVER_IMPL, DEFAULT_ACCESS_DRIVER);
         properties.put("ACCESS_POINTS", omsNamesrv);
         properties.put("REGION", "namespace");
         properties.put("instanceName", instanceName);
@@ -87,7 +82,7 @@ public class RocketMQConsumerImpl implements MeshMQPushConsumer {
         } else {
             properties.put("MESSAGE_MODEL", MessageModel.CLUSTERING.name());
         }
-        MessagingAccessPoint messagingAccessPoint = OMS.builder().build(properties);
+        MessagingAccessPoint messagingAccessPoint = new MessagingAccessPointImpl(properties);
         pushConsumer = (PushConsumerImpl) messagingAccessPoint.createConsumer(properties);
     }
 
diff --git a/eventmesh-connector-plugin/eventmesh-connector-rocketmq/src/main/java/org/apache/eventmesh/connector/rocketmq/producer/RocketMQProducerImpl.java b/eventmesh-connector-plugin/eventmesh-connector-rocketmq/src/main/java/org/apache/eventmesh/connector/rocketmq/producer/RocketMQProducerImpl.java
index eba5208..75e2360 100644
--- a/eventmesh-connector-plugin/eventmesh-connector-rocketmq/src/main/java/org/apache/eventmesh/connector/rocketmq/producer/RocketMQProducerImpl.java
+++ b/eventmesh-connector-plugin/eventmesh-connector-rocketmq/src/main/java/org/apache/eventmesh/connector/rocketmq/producer/RocketMQProducerImpl.java
@@ -31,6 +31,7 @@ import io.openmessaging.api.SendResult;
 
 import org.apache.eventmesh.api.RRCallback;
 import org.apache.eventmesh.api.producer.MeshMQProducer;
+import org.apache.eventmesh.connector.rocketmq.MessagingAccessPointImpl;
 import org.apache.eventmesh.connector.rocketmq.common.EventMeshConstants;
 import org.apache.eventmesh.connector.rocketmq.config.ClientConfiguration;
 import org.apache.eventmesh.connector.rocketmq.config.ConfigurationWrapper;
@@ -48,8 +49,6 @@ public class RocketMQProducerImpl implements MeshMQProducer {
 
     private ProducerImpl producer;
 
-    public final String DEFAULT_ACCESS_DRIVER = "org.apache.eventmesh.connector.rocketmq.MessagingAccessPointImpl";
-
     @Override
     public synchronized void init(Properties keyValue) {
         ConfigurationWrapper configurationWrapper =
@@ -62,14 +61,13 @@ public class RocketMQProducerImpl implements MeshMQProducer {
 
         String omsNamesrv = clientConfiguration.namesrvAddr;
         Properties properties = new Properties();
-        properties.put(OMSBuiltinKeys.DRIVER_IMPL, DEFAULT_ACCESS_DRIVER);
         properties.put("ACCESS_POINTS", omsNamesrv);
         properties.put("REGION", "namespace");
         properties.put("RMQ_PRODUCER_GROUP", producerGroup);
         properties.put("OPERATION_TIMEOUT", 3000);
         properties.put("PRODUCER_ID", producerGroup);
 
-        MessagingAccessPoint messagingAccessPoint = OMS.builder().build(properties);
+        MessagingAccessPoint messagingAccessPoint = new MessagingAccessPointImpl(properties);
         producer = (ProducerImpl) messagingAccessPoint.createProducer(properties);
 
     }
diff --git a/eventmesh-registry-plugin/build.gradle b/eventmesh-registry-plugin/build.gradle
index 87e4a9b..2944f98 100644
--- a/eventmesh-registry-plugin/build.gradle
+++ b/eventmesh-registry-plugin/build.gradle
@@ -14,24 +14,3 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-
-task copyRegistryPlugin(dependsOn: ['jar']) {
-    doFirst {
-        new File(projectDir, '../eventmesh-registry-plugin/dist/apps').mkdir()
-        new File(projectDir, '../dist/plugin/registry').mkdirs()
-    }
-    doLast {
-        copy {
-            into('../eventmesh-registry-plugin/dist/apps/')
-            from project.jar.getArchivePath()
-            exclude {
-                "eventmesh-registry-plugin-${version}.jar"
-                "eventmesh-registry-api-${version}.jar"
-            }
-        }
-        copy {
-            into '../dist/plugin/registry'
-            from "../eventmesh-registry-plugin/dist/apps/eventmesh-registry-rocketmq-namesrv-${version}.jar"
-        }
-    }
-}
\ No newline at end of file
diff --git a/eventmesh-registry-plugin/eventmesh-registry-api/src/main/java/org/apache/eventmesh/api/registry/RegistryService.java b/eventmesh-registry-plugin/eventmesh-registry-api/src/main/java/org/apache/eventmesh/api/registry/RegistryService.java
index e161b71..5363b2d 100644
--- a/eventmesh-registry-plugin/eventmesh-registry-api/src/main/java/org/apache/eventmesh/api/registry/RegistryService.java
+++ b/eventmesh-registry-plugin/eventmesh-registry-api/src/main/java/org/apache/eventmesh/api/registry/RegistryService.java
@@ -20,12 +20,13 @@ import org.apache.eventmesh.api.exception.RegistryException;
 import org.apache.eventmesh.api.registry.dto.EventMeshDataInfo;
 import org.apache.eventmesh.api.registry.dto.EventMeshRegisterInfo;
 import org.apache.eventmesh.api.registry.dto.EventMeshUnRegisterInfo;
+import org.apache.eventmesh.spi.EventMeshExtensionType;
 import org.apache.eventmesh.spi.EventMeshSPI;
 
 import java.util.List;
 import java.util.Map;
 
-@EventMeshSPI(isSingleton = true)
+@EventMeshSPI(isSingleton = true, eventMeshExtensionType = EventMeshExtensionType.REGISTRY)
 public interface RegistryService {
     void init() throws RegistryException;
 
diff --git a/eventmesh-security-plugin/build.gradle b/eventmesh-security-plugin/build.gradle
index dd414e3..d973dce 100644
--- a/eventmesh-security-plugin/build.gradle
+++ b/eventmesh-security-plugin/build.gradle
@@ -13,25 +13,4 @@
  * 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.
- */
-
-task copyAclPlugin(dependsOn: ['jar']) {
-    doFirst {
-        new File(projectDir, '../eventmesh-security-plugin/dist/apps').mkdir()
-        new File(projectDir, '../dist/plugin/security').mkdirs()
-    }
-    doLast {
-        copy {
-            into('../eventmesh-security-plugin/dist/apps/')
-            from project.jar.getArchivePath()
-            exclude {
-                "eventmesh-security-plugin-${version}.jar"
-                "eventmesh-security-api-${version}.jar"
-            }
-        }
-        copy {
-            into '../dist/plugin/security'
-            from "../eventmesh-security-plugin/dist/apps/eventmesh-security-acl-${version}.jar"
-        }
-    }
-}
\ No newline at end of file
+ */
\ No newline at end of file
diff --git a/eventmesh-security-plugin/eventmesh-security-api/src/main/java/org/apache/eventmesh/api/acl/AclService.java b/eventmesh-security-plugin/eventmesh-security-api/src/main/java/org/apache/eventmesh/api/acl/AclService.java
index 3502e90..38b2f1a 100644
--- a/eventmesh-security-plugin/eventmesh-security-api/src/main/java/org/apache/eventmesh/api/acl/AclService.java
+++ b/eventmesh-security-plugin/eventmesh-security-api/src/main/java/org/apache/eventmesh/api/acl/AclService.java
@@ -17,11 +17,12 @@
 package org.apache.eventmesh.api.acl;
 
 import org.apache.eventmesh.api.exception.AclException;
+import org.apache.eventmesh.spi.EventMeshExtensionType;
 import org.apache.eventmesh.spi.EventMeshSPI;
 
 import java.util.Properties;
 
-@EventMeshSPI(isSingleton = true)
+@EventMeshSPI(isSingleton = true, eventMeshExtensionType = EventMeshExtensionType.SECURITY)
 public interface AclService {
     void init() throws AclException;
 
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 6388809..a096f17 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
@@ -72,16 +72,16 @@ public enum EventMeshExtensionFactory {
     }
 
     @SuppressWarnings("unchecked")
-    private static <T> T getSingletonExtension(Class<T> extensionType, String extensionName) {
-        return (T) EXTENSION_INSTANCE_CACHE.computeIfAbsent(extensionName, name -> {
-            Class<T> extensionInstanceClass = getExtensionClass(extensionType, extensionName);
+    private static <T> T getSingletonExtension(Class<T> extensionType, String extensionInstanceName) {
+        return (T) EXTENSION_INSTANCE_CACHE.computeIfAbsent(extensionInstanceName, name -> {
+            Class<T> extensionInstanceClass = getExtensionInstanceClass(extensionType, extensionInstanceName);
             try {
                 if (extensionInstanceClass == null) {
                     return null;
                 }
                 T extensionInstance = extensionInstanceClass.newInstance();
-                logger.info("initialize extension instance success, extensionType: {}, extensionName: {}",
-                        extensionType, extensionName);
+                logger.info("initialize extension instance success, extensionType: {}, extensionInstanceName: {}",
+                        extensionType, extensionInstanceName);
                 return extensionInstance;
             } catch (InstantiationException | IllegalAccessException e) {
                 throw new ExtensionException("Extension initialize error", e);
@@ -89,15 +89,15 @@ public enum EventMeshExtensionFactory {
         });
     }
 
-    private static <T> T getPrototypeExtension(Class<T> extensionType, String extensionName) {
-        Class<T> extensionInstanceClass = getExtensionClass(extensionType, extensionName);
+    private static <T> T getPrototypeExtension(Class<T> extensionType, String extensionInstanceName) {
+        Class<T> extensionInstanceClass = getExtensionInstanceClass(extensionType, extensionInstanceName);
         try {
             if (extensionInstanceClass == null) {
                 return null;
             }
             T extensionInstance = extensionInstanceClass.newInstance();
             logger.info("initialize extension instance success, extensionType: {}, extensionName: {}",
-                    extensionType, extensionName);
+                    extensionType, extensionInstanceName);
             return extensionInstance;
         } catch (InstantiationException | IllegalAccessException e) {
             throw new ExtensionException("Extension initialize error", e);
@@ -105,10 +105,10 @@ public enum EventMeshExtensionFactory {
     }
 
     @SuppressWarnings("unchecked")
-    private static <T> Class<T> getExtensionClass(Class<T> extensionType, String extensionName) {
+    private static <T> Class<T> getExtensionInstanceClass(Class<T> extensionType, String extensionInstanceName) {
         for (ExtensionClassLoader extensionClassLoader : extensionClassLoaders) {
-            Map<String, Class<?>> extensionClassMap = extensionClassLoader.loadExtensionClass(extensionType);
-            Class<?> instanceClass = extensionClassMap.get(extensionName);
+            Map<String, Class<?>> extensionInstanceClassMap = extensionClassLoader.loadExtensionClass(extensionType, extensionInstanceName);
+            Class<?> instanceClass = extensionInstanceClassMap.get(extensionInstanceName);
             if (instanceClass != null) {
                 return (Class<T>) instanceClass;
             }
diff --git a/eventmesh-spi/src/main/java/org/apache/eventmesh/spi/EventMeshSPI.java b/eventmesh-spi/src/main/java/org/apache/eventmesh/spi/EventMeshExtensionType.java
similarity index 64%
copy from eventmesh-spi/src/main/java/org/apache/eventmesh/spi/EventMeshSPI.java
copy to eventmesh-spi/src/main/java/org/apache/eventmesh/spi/EventMeshExtensionType.java
index 48b0ef0..786ae72 100644
--- a/eventmesh-spi/src/main/java/org/apache/eventmesh/spi/EventMeshSPI.java
+++ b/eventmesh-spi/src/main/java/org/apache/eventmesh/spi/EventMeshExtensionType.java
@@ -17,24 +17,24 @@
 
 package org.apache.eventmesh.spi;
 
-import java.lang.annotation.Documented;
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
 /**
- * Just as a marker for SPI
+ * An Extension can be defined by extensionTypeName and extensionInstanceName
  */
-@Documented
-@Retention(RetentionPolicy.RUNTIME)
-@Target({ElementType.TYPE})
-public @interface EventMeshSPI {
+public enum EventMeshExtensionType {
+    UNKNOWN("unknown"),
+    CONNECTOR("connector"),
+    REGISTRY("registry"),
+    SECURITY("security"),
+    ;
 
-    /**
-     * If true, the spi instance is singleton
-     */
-    boolean isSingleton() default false;
+    private final String extensionTypeName;
 
-}
+    EventMeshExtensionType(String extensionTypeName) {
+        this.extensionTypeName = extensionTypeName;
+    }
 
+    public String getExtensionTypeName() {
+        return extensionTypeName;
+    }
+
+}
diff --git a/eventmesh-spi/src/main/java/org/apache/eventmesh/spi/EventMeshSPI.java b/eventmesh-spi/src/main/java/org/apache/eventmesh/spi/EventMeshSPI.java
index 48b0ef0..364d197 100644
--- a/eventmesh-spi/src/main/java/org/apache/eventmesh/spi/EventMeshSPI.java
+++ b/eventmesh-spi/src/main/java/org/apache/eventmesh/spi/EventMeshSPI.java
@@ -36,5 +36,11 @@ public @interface EventMeshSPI {
      */
     boolean isSingleton() default false;
 
+    /**
+     * {@link EventMeshExtensionType}
+     * @return extension type
+     */
+    EventMeshExtensionType eventMeshExtensionType();
+
 }
 
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
new file mode 100644
index 0000000..c53543b
--- /dev/null
+++ b/eventmesh-spi/src/main/java/org/apache/eventmesh/spi/loader/EventMeshUrlClassLoader.java
@@ -0,0 +1,56 @@
+/*
+ * 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.eventmesh.spi.loader;
+
+import org.apache.commons.collections4.CollectionUtils;
+
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.util.List;
+
+public class EventMeshUrlClassLoader extends URLClassLoader {
+
+    public static EventMeshUrlClassLoader getInstance() {
+        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.
+     * <p>
+     * More detail see {@link URLClassLoader#addURL(URL)}
+     * @param urls
+     */
+    public void addUrls(List<URL> urls) {
+        if (CollectionUtils.isEmpty(urls)) {
+            return;
+        }
+        urls.forEach(this::addURL);
+    }
+
+    private EventMeshUrlClassLoader(URL[] urls, ClassLoader parent) {
+        super(urls, parent);
+    }
+
+    private static class EventMeshUrlClassLoaderHolder {
+        private static EventMeshUrlClassLoader instance = new EventMeshUrlClassLoader(new URL[0], Thread.currentThread().getContextClassLoader());
+    }
+}
diff --git a/eventmesh-spi/src/main/java/org/apache/eventmesh/spi/loader/ExtensionClassLoader.java b/eventmesh-spi/src/main/java/org/apache/eventmesh/spi/loader/ExtensionClassLoader.java
index feca359..3e13c33 100644
--- a/eventmesh-spi/src/main/java/org/apache/eventmesh/spi/loader/ExtensionClassLoader.java
+++ b/eventmesh-spi/src/main/java/org/apache/eventmesh/spi/loader/ExtensionClassLoader.java
@@ -29,11 +29,12 @@ import java.util.Map;
 public interface ExtensionClassLoader {
 
     /**
-     * load
+     * load extension class
      *
-     * @param extensionType extension type class
-     * @param <T>           extension type
+     * @param extensionType         extension type class
+     * @param extensionInstanceName extension instance name
+     * @param <T>                   extension type
      * @return extension instance name to extension instance class
      */
-    <T> Map<String, Class<?>> loadExtensionClass(Class<T> extensionType);
+    <T> Map<String, Class<?>> loadExtensionClass(Class<T> extensionType, String extensionInstanceName);
 }
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 dde9fb9..3692bc1 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
@@ -17,8 +17,9 @@
 
 package org.apache.eventmesh.spi.loader;
 
+import com.google.common.base.Joiner;
 import com.google.common.collect.Lists;
-import org.apache.commons.collections4.CollectionUtils;
+import org.apache.eventmesh.spi.EventMeshSPI;
 import org.apache.eventmesh.spi.ExtensionException;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -28,6 +29,7 @@ import java.io.IOException;
 import java.io.InputStream;
 import java.net.URL;
 import java.net.URLClassLoader;
+import java.nio.file.Paths;
 import java.util.ArrayList;
 import java.util.Enumeration;
 import java.util.HashMap;
@@ -47,25 +49,29 @@ public class JarExtensionClassLoader implements ExtensionClassLoader {
             new ConcurrentHashMap<>(16);
 
     private static final String EVENTMESH_EXTENSION_PLUGIN_DIR = System.getProperty("eventMeshPluginDir",
-            "./plugin");
+            Joiner.on(File.separator).join(Lists.newArrayList(".", "plugin")));
 
-    private static final String EVENTMESH_EXTENSION_META_DIR = "META-INF/eventmesh/";
+    // META-INF/eventmesh
+    private static final String EVENTMESH_EXTENSION_META_DIR = Paths.get("META-INF", "eventmesh").toString();
 
     @Override
-    public <T> Map<String, Class<?>> loadExtensionClass(Class<T> extensionType) {
-        return EXTENSION_CLASS_CACHE.computeIfAbsent(extensionType, this::doLoadExtensionClass);
+    public <T> Map<String, Class<?>> loadExtensionClass(Class<T> extensionType, String extensionInstanceName) {
+        return EXTENSION_CLASS_CACHE.computeIfAbsent(extensionType, t -> doLoadExtensionClass(t, extensionInstanceName));
     }
 
-    private <T> Map<String, Class<?>> doLoadExtensionClass(Class<T> extensionType) {
-        Map<String, Class<?>> extensionMap = new HashMap<>();
+    private <T> Map<String, Class<?>> doLoadExtensionClass(Class<T> extensionType, String extensionInstanceName) {
+        Map<String, Class<?>> extensionMap = new HashMap<>(16);
+        EventMeshSPI eventMeshSPIAnnotation = extensionType.getAnnotation(EventMeshSPI.class);
 
-        List<URL> pluginJarPaths = loadJarPathFromResource(EVENTMESH_EXTENSION_PLUGIN_DIR);
-        if (CollectionUtils.isEmpty(pluginJarPaths)) {
-            return extensionMap;
-        }
+        String pluginDir = Paths.get(
+                EVENTMESH_EXTENSION_PLUGIN_DIR,
+                eventMeshSPIAnnotation.eventMeshExtensionType().getExtensionTypeName(),
+                extensionInstanceName
+        ).toString();
 
-        String extensionFileName = EVENTMESH_EXTENSION_META_DIR + extensionType.getName();
-        URLClassLoader urlClassLoader = URLClassLoader.newInstance(pluginJarPaths.toArray(new URL[0]));
+        String extensionFileName = EVENTMESH_EXTENSION_META_DIR + File.separator + extensionType.getName();
+        EventMeshUrlClassLoader urlClassLoader = EventMeshUrlClassLoader.getInstance();
+        urlClassLoader.addUrls(loadJarPathFromResource(pluginDir));
         try {
             Enumeration<URL> extensionUrls = urlClassLoader.getResources(extensionFileName);
             if (extensionUrls != null) {
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 59d45e1..ec07f4e 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
@@ -43,14 +43,14 @@ public class MetaInfExtensionClassLoader implements ExtensionClassLoader {
     private static final String EVENTMESH_EXTENSION_META_DIR = "META-INF/eventmesh/";
 
     @Override
-    public <T> Map<String, Class<?>> loadExtensionClass(Class<T> extensionType) {
+    public <T> Map<String, Class<?>> loadExtensionClass(Class<T> extensionType, String extensionInstanceName) {
         return EXTENSION_CLASS_CACHE.computeIfAbsent(extensionType, this::doLoadExtensionClass);
     }
 
     private <T> Map<String, Class<?>> doLoadExtensionClass(Class<T> extensionType) {
         Map<String, Class<?>> extensionMap = new HashMap<>();
         String extensionFileName = EVENTMESH_EXTENSION_META_DIR + extensionType.getName();
-        ClassLoader classLoader = MetaInfExtensionClassLoader.class.getClassLoader();
+        ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
         try {
             Enumeration<URL> extensionUrls = classLoader.getResources(extensionFileName);
             if (extensionUrls != null) {
diff --git a/eventmesh-spi/src/test/java/org/apache/eventmesh/spi/example/TestPrototypeExtension.java b/eventmesh-spi/src/test/java/org/apache/eventmesh/spi/example/TestPrototypeExtension.java
index 0267c90..06e4549 100644
--- a/eventmesh-spi/src/test/java/org/apache/eventmesh/spi/example/TestPrototypeExtension.java
+++ b/eventmesh-spi/src/test/java/org/apache/eventmesh/spi/example/TestPrototypeExtension.java
@@ -17,9 +17,10 @@
 
 package org.apache.eventmesh.spi.example;
 
+import org.apache.eventmesh.spi.EventMeshExtensionType;
 import org.apache.eventmesh.spi.EventMeshSPI;
 
-@EventMeshSPI(isSingleton = false)
+@EventMeshSPI(isSingleton = false, eventMeshExtensionType = EventMeshExtensionType.UNKNOWN)
 public interface TestPrototypeExtension {
 
     void hello();
diff --git a/eventmesh-spi/src/test/java/org/apache/eventmesh/spi/example/TestSingletonExtension.java b/eventmesh-spi/src/test/java/org/apache/eventmesh/spi/example/TestSingletonExtension.java
index 11c61fe..b78744d 100644
--- a/eventmesh-spi/src/test/java/org/apache/eventmesh/spi/example/TestSingletonExtension.java
+++ b/eventmesh-spi/src/test/java/org/apache/eventmesh/spi/example/TestSingletonExtension.java
@@ -17,9 +17,10 @@
 
 package org.apache.eventmesh.spi.example;
 
+import org.apache.eventmesh.spi.EventMeshExtensionType;
 import org.apache.eventmesh.spi.EventMeshSPI;
 
-@EventMeshSPI(isSingleton = true)
+@EventMeshSPI(isSingleton = true, eventMeshExtensionType = EventMeshExtensionType.UNKNOWN)
 public interface TestSingletonExtension {
 
     void hello();

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