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