Skip to content

Commit 643f059

Browse files
authored
[ISSUE #4129]Enhance the functionality of EventMeshExtensionFactory (#4131)
1 parent 1e59cdf commit 643f059

File tree

5 files changed

+163
-19
lines changed

5 files changed

+163
-19
lines changed

eventmesh-spi/src/main/java/org/apache/eventmesh/spi/EventMeshExtensionFactory.java

+77-19
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import java.util.ArrayList;
3030
import java.util.List;
3131
import java.util.Map;
32+
import java.util.Objects;
3233
import java.util.concurrent.ConcurrentHashMap;
3334

3435

@@ -43,7 +44,7 @@ public class EventMeshExtensionFactory {
4344

4445
private static final List<ExtensionClassLoader> EXTENSION_CLASS_LOADERS = new ArrayList<>();
4546

46-
private static final ConcurrentHashMap<String, Object> EXTENSION_INSTANCE_CACHE = new ConcurrentHashMap<>(16);
47+
private static final ConcurrentHashMap<Extension, Object> EXTENSION_INSTANCE_CACHE = new ConcurrentHashMap<>(16);
4748

4849
static {
4950
EXTENSION_CLASS_LOADERS.add(MetaInfExtensionClassLoader.getInstance());
@@ -56,52 +57,72 @@ private EventMeshExtensionFactory() {
5657
}
5758

5859
/**
59-
* @param extensionType extension plugin class type
60-
* @param extensionName extension instance name
61-
* @param <T> the type of the plugin
60+
* Get an instance of an extension plugin.
61+
*
62+
* @param extensionClass extension plugin class type
63+
* @param extensionName extension instance name
64+
* @param <T> the type of the plugin
6265
* @return plugin instance
6366
*/
64-
public static <T> T getExtension(Class<T> extensionType, String extensionName) {
65-
if (extensionType == null) {
66-
throw new ExtensionException("extensionType is null");
67+
public static <T> T getExtension(Class<T> extensionClass, String extensionName) {
68+
if (extensionClass == null) {
69+
throw new ExtensionException("extensionClass is null");
6770
}
6871
if (StringUtils.isEmpty(extensionName)) {
6972
throw new ExtensionException("extensionName is null");
7073
}
71-
if (!extensionType.isInterface() || !extensionType.isAnnotationPresent(EventMeshSPI.class)) {
72-
throw new ExtensionException(String.format("extensionType:%s is invalided", extensionType));
74+
if (!extensionClass.isInterface() || !extensionClass.isAnnotationPresent(EventMeshSPI.class)) {
75+
throw new ExtensionException(String.format("extensionClass:%s is invalided", extensionClass));
7376
}
74-
EventMeshSPI eventMeshSPIAnnotation = extensionType.getAnnotation(EventMeshSPI.class);
77+
EventMeshSPI eventMeshSPIAnnotation = extensionClass.getAnnotation(EventMeshSPI.class);
7578
if (eventMeshSPIAnnotation.isSingleton()) {
76-
return getSingletonExtension(extensionType, extensionName);
79+
return getSingletonExtension(extensionClass, eventMeshSPIAnnotation, extensionName);
7780
}
78-
return getPrototypeExtension(extensionType, extensionName);
81+
return getPrototypeExtension(extensionClass, extensionName);
7982
}
8083

84+
/**
85+
* Get a singleton instance of an extension plugin.
86+
*
87+
* @param extensionClass the type of the extension plugin
88+
* @param spi the type of the spi
89+
* @param extensionInstanceName the name of the extension instance
90+
* @param <T> the type of the extension plugin
91+
* @return a singleton instance of the extension plugin
92+
*/
8193
@SuppressWarnings("unchecked")
82-
private static <T> T getSingletonExtension(Class<T> extensionType, String extensionInstanceName) {
83-
return (T) EXTENSION_INSTANCE_CACHE.computeIfAbsent(extensionInstanceName, name -> {
84-
Class<T> extensionInstanceClass = getExtensionInstanceClass(extensionType, extensionInstanceName);
94+
private static <T> T getSingletonExtension(Class<T> extensionClass, EventMeshSPI spi, String extensionInstanceName) {
95+
return (T) EXTENSION_INSTANCE_CACHE.computeIfAbsent(new Extension(spi, extensionInstanceName), name -> {
96+
Class<T> extensionInstanceClass = getExtensionInstanceClass(extensionClass, extensionInstanceName);
8597
if (extensionInstanceClass == null) {
98+
log.warn("Get extension instance class {} is null", extensionClass.getName());
8699
return null;
87100
}
88101
try {
89102
T extensionInstance = extensionInstanceClass.getDeclaredConstructor().newInstance();
90103
ConfigService.getInstance().populateConfigForObject(extensionInstance);
91104

92-
log.info("initialize extension instance success, extensionType: {}, extensionInstanceName: {}",
93-
extensionType, extensionInstanceName);
105+
log.info("initialize extension instance success, extensionClass: {}, extensionInstanceName: {}",
106+
extensionClass, extensionInstanceName);
94107
return extensionInstance;
95108
} catch (NoSuchMethodException | InstantiationException | IllegalAccessException | InvocationTargetException e) {
96109
throw new ExtensionException("Extension initialize error", e);
97110
} catch (NoSuchFieldException | IOException e) {
98-
log.error("initialize extension instance config failed, extensionType: {}, extensionInstanceName: {}",
99-
extensionType, extensionInstanceName, e);
111+
log.error("initialize extension instance config failed, extensionClass: {}, extensionInstanceName: {}",
112+
extensionClass, extensionInstanceName, e);
100113
throw new ExtensionException("Extension initialize error", e);
101114
}
102115
});
103116
}
104117

118+
/**
119+
* Get a new instance of an extension plugin.
120+
*
121+
* @param extensionType the type of the extension plugin
122+
* @param extensionInstanceName the name of the extension instance
123+
* @param <T> the type of the extension plugin
124+
* @return a new instance of the extension plugin
125+
*/
105126
private static <T> T getPrototypeExtension(Class<T> extensionType, String extensionInstanceName) {
106127
Class<T> extensionInstanceClass = getExtensionInstanceClass(extensionType, extensionInstanceName);
107128
if (extensionInstanceClass == null) {
@@ -123,6 +144,14 @@ private static <T> T getPrototypeExtension(Class<T> extensionType, String extens
123144
}
124145
}
125146

147+
/**
148+
* Get the class of an extension instance.
149+
*
150+
* @param extensionType the type of the extension instance
151+
* @param extensionInstanceName the name of the extension instance
152+
* @param <T> the type of the extension instance
153+
* @return the class of the extension instance
154+
*/
126155
@SuppressWarnings("unchecked")
127156
private static <T> Class<T> getExtensionInstanceClass(Class<T> extensionType, String extensionInstanceName) {
128157
for (ExtensionClassLoader extensionClassLoader : EXTENSION_CLASS_LOADERS) {
@@ -134,4 +163,33 @@ private static <T> Class<T> getExtensionInstanceClass(Class<T> extensionType, St
134163
}
135164
return null;
136165
}
166+
167+
private static class Extension {
168+
169+
private EventMeshSPI spi;
170+
171+
private String extensionInstanceName;
172+
173+
public Extension(EventMeshSPI spi, String extensionInstanceName) {
174+
this.spi = spi;
175+
this.extensionInstanceName = extensionInstanceName;
176+
}
177+
178+
@Override
179+
public boolean equals(Object o) {
180+
if (this == o) {
181+
return true;
182+
}
183+
if (!(o instanceof Extension)) {
184+
return false;
185+
}
186+
Extension extension = (Extension) o;
187+
return Objects.equals(spi, extension.spi) && Objects.equals(extensionInstanceName, extension.extensionInstanceName);
188+
}
189+
190+
@Override
191+
public int hashCode() {
192+
return Objects.hash(spi, extensionInstanceName);
193+
}
194+
}
137195
}

eventmesh-spi/src/test/java/org/apache/eventmesh/spi/EventMeshExtensionFactoryTest.java

+9
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
package org.apache.eventmesh.spi;
1919

20+
import org.apache.eventmesh.spi.example.TestAnotherSingletonExtension;
2021
import org.apache.eventmesh.spi.example.TestPrototypeExtension;
2122
import org.apache.eventmesh.spi.example.TestSingletonExtension;
2223

@@ -30,6 +31,14 @@ public void testGetSingletonExtension() {
3031
TestSingletonExtension extensionA = EventMeshExtensionFactory.getExtension(TestSingletonExtension.class, "singletonExtension");
3132
TestSingletonExtension extensionB = EventMeshExtensionFactory.getExtension(TestSingletonExtension.class, "singletonExtension");
3233
Assert.assertSame(extensionA, extensionB);
34+
35+
TestAnotherSingletonExtension singletonExtension = EventMeshExtensionFactory.getExtension(TestAnotherSingletonExtension.class,
36+
"singletonExtension");
37+
Assert.assertNotNull(singletonExtension);
38+
TestSingletonExtension singletonExtension1 = EventMeshExtensionFactory.getExtension(TestSingletonExtension.class, "singletonExtension");
39+
Assert.assertNotNull(singletonExtension1);
40+
41+
3342
}
3443

3544
@Test
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to You under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
package org.apache.eventmesh.spi.example;
19+
20+
21+
import lombok.extern.slf4j.Slf4j;
22+
23+
@Slf4j
24+
public class AnotherSingletonExtension implements TestAnotherSingletonExtension {
25+
26+
@Override
27+
public void hello() {
28+
log.info("I am SingletonExtension");
29+
}
30+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to You under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
package org.apache.eventmesh.spi.example;
19+
20+
import org.apache.eventmesh.spi.EventMeshExtensionType;
21+
import org.apache.eventmesh.spi.EventMeshSPI;
22+
23+
/**
24+
* TestAnotherSingletonExtension
25+
*/
26+
@EventMeshSPI(eventMeshExtensionType = EventMeshExtensionType.SECURITY)
27+
public interface TestAnotherSingletonExtension {
28+
29+
void hello();
30+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
#
2+
# Licensed to the Apache Software Foundation (ASF) under one or more
3+
# contributor license agreements. See the NOTICE file distributed with
4+
# this work for additional information regarding copyright ownership.
5+
# The ASF licenses this file to You under the Apache License, Version 2.0
6+
# (the "License"); you may not use this file except in compliance with
7+
# the License. You may obtain a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing, software
12+
# distributed under the License is distributed on an "AS IS" BASIS,
13+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
# See the License for the specific language governing permissions and
15+
# limitations under the License.
16+
17+
singletonExtension=org.apache.eventmesh.spi.example.AnotherSingletonExtension

0 commit comments

Comments
 (0)