diff --git a/dubbo-common/src/main/java/com/alibaba/dubbo/common/ExtensionLoader.java b/dubbo-common/src/main/java/com/alibaba/dubbo/common/ExtensionLoader.java index c0c8a33ec9..4d4ffcffd7 100644 --- a/dubbo-common/src/main/java/com/alibaba/dubbo/common/ExtensionLoader.java +++ b/dubbo-common/src/main/java/com/alibaba/dubbo/common/ExtensionLoader.java @@ -72,6 +72,7 @@ public class ExtensionLoader { private volatile Class cachedAdaptiveClass = null; private final Reference cachedAdaptiveInstance = new Reference(); + private volatile Throwable createAdaptiveInstanceError; private Set> cachedWrapperClasses; @@ -135,17 +136,35 @@ public class ExtensionLoader { public T getAdaptiveExtension() { Object instance = cachedAdaptiveInstance.get(); if (instance == null) { - synchronized (cachedAdaptiveInstance) { - instance = cachedAdaptiveInstance.get(); - if (instance == null) { - instance = createAdaptiveExtension(); - cachedAdaptiveInstance.set(instance); + if(createAdaptiveInstanceError == null) { + synchronized (cachedAdaptiveInstance) { + instance = cachedAdaptiveInstance.get(); + if (instance == null) { + try { + instance = createAdaptiveExtension(); + cachedAdaptiveInstance.set(instance); + } catch (Throwable t) { + createAdaptiveInstanceError = t; + rethrowAsRuntime(t, "fail to create adaptive instance: "); + } + } } } + else { + rethrowAsRuntime(createAdaptiveInstanceError, "fail to create adaptive instance: "); + } } + return (T) instance; } + private static void rethrowAsRuntime(Throwable t, String message) { + if(t instanceof RuntimeException) + throw (RuntimeException)t; + else + throw new IllegalStateException(message + t.toString(), t); + } + @SuppressWarnings("unchecked") private T createExtension(String name) { Class clazz = getExtensionClasses().get(name); @@ -269,12 +288,12 @@ public class ExtensionLoader { } else { try { clazz.getConstructor(type); - Set> autoproxies = cachedWrapperClasses; - if (autoproxies == null) { + Set> wrappers = cachedWrapperClasses; + if (wrappers == null) { cachedWrapperClasses = new ConcurrentHashSet>(); - autoproxies = cachedWrapperClasses; + wrappers = cachedWrapperClasses; } - autoproxies.add(clazz); + wrappers.add(clazz); } catch (NoSuchMethodException e) { clazz.getConstructor(); Extension extension = clazz.getAnnotation(Extension.class); @@ -348,7 +367,7 @@ public class ExtensionLoader { } // 完全没有Adaptive方法,则不需要生成Adaptive类 if(! hasAdaptiveAnnotation) - throw new IllegalStateException("No such adaptive class for extension " + type.getName()); + throw new IllegalStateException("No adaptive method on extension " + type.getName() + ", refuse to create the adaptive class!"); ClassGenerator cg = ClassGenerator.newInstance(classLoader); cg.setClassName(type.getName() + "$Adpative"); @@ -505,4 +524,9 @@ public class ExtensionLoader { return classLoader; } + @Override + public String toString() { + return this.getClass().getName() + "[" + type.getName() + "]"; + } + } \ No newline at end of file diff --git a/dubbo-common/src/test/java/com/alibaba/dubbo/common/extensionloader/ExtensionLoaderTest.java b/dubbo-common/src/test/java/com/alibaba/dubbo/common/extensionloader/ExtensionLoaderTest.java index ca411be27d..b395be3e97 100644 --- a/dubbo-common/src/test/java/com/alibaba/dubbo/common/extensionloader/ExtensionLoaderTest.java +++ b/dubbo-common/src/test/java/com/alibaba/dubbo/common/extensionloader/ExtensionLoaderTest.java @@ -16,7 +16,7 @@ package com.alibaba.dubbo.common.extensionloader; import static org.hamcrest.CoreMatchers.anyOf; -import static org.hamcrest.CoreMatchers.instanceOf; +import static org.hamcrest.CoreMatchers.*; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertThat; @@ -41,8 +41,8 @@ import com.alibaba.dubbo.common.extensionloader.ext2.UrlHolder; import com.alibaba.dubbo.common.extensionloader.ext3.Ext3; import com.alibaba.dubbo.common.extensionloader.ext4.Ext4; import com.alibaba.dubbo.common.extensionloader.ext5.Ext5NoAdaptiveMethod; -import com.alibaba.dubbo.common.extensionloader.ext5.impl.Ext5AutoProxy1; -import com.alibaba.dubbo.common.extensionloader.ext5.impl.Ext5AutoProxy2; +import com.alibaba.dubbo.common.extensionloader.ext5.impl.Ext5Wrapper1; +import com.alibaba.dubbo.common.extensionloader.ext5.impl.Ext5Wrapper2; import com.alibaba.dubbo.common.extensionloader.ext6_inject.Ext6; import com.alibaba.dubbo.common.extensionloader.ext6_inject.impl.Ext6Impl2; @@ -57,31 +57,31 @@ public class ExtensionLoaderTest { } @Test - public void test_getExtension_WithAutoProxy() throws Exception { + public void test_getExtension_WithWrapper() throws Exception { Ext5NoAdaptiveMethod impl1 = ExtensionLoader.getExtensionLoader(Ext5NoAdaptiveMethod.class).getExtension("impl1"); - assertThat(impl1, anyOf(instanceOf(Ext5AutoProxy1.class), instanceOf(Ext5AutoProxy2.class))); + assertThat(impl1, anyOf(instanceOf(Ext5Wrapper1.class), instanceOf(Ext5Wrapper2.class))); Ext5NoAdaptiveMethod impl2 = ExtensionLoader.getExtensionLoader(Ext5NoAdaptiveMethod.class).getExtension("impl2") ; - assertThat(impl2, anyOf(instanceOf(Ext5AutoProxy1.class), instanceOf(Ext5AutoProxy2.class))); + assertThat(impl2, anyOf(instanceOf(Ext5Wrapper1.class), instanceOf(Ext5Wrapper2.class))); URL url = new URL("p1", "1.2.3.4", 1010, "path1"); - int echoCount1 = Ext5AutoProxy1.echoCount.get(); - int echoCount2 = Ext5AutoProxy2.echoCount.get(); - int yellCount1 = Ext5AutoProxy1.yellCount.get(); - int yellCount2 = Ext5AutoProxy2.yellCount.get(); + int echoCount1 = Ext5Wrapper1.echoCount.get(); + int echoCount2 = Ext5Wrapper2.echoCount.get(); + int yellCount1 = Ext5Wrapper1.yellCount.get(); + int yellCount2 = Ext5Wrapper2.yellCount.get(); assertEquals("Ext5Impl1-echo", impl1.echo(url, "ha")); - assertEquals(echoCount1 + 1, Ext5AutoProxy1.echoCount.get()); - assertEquals(echoCount2 + 1, Ext5AutoProxy2.echoCount.get()); - assertEquals(yellCount1, Ext5AutoProxy1.yellCount.get()); - assertEquals(yellCount2, Ext5AutoProxy2.yellCount.get()); + assertEquals(echoCount1 + 1, Ext5Wrapper1.echoCount.get()); + assertEquals(echoCount2 + 1, Ext5Wrapper2.echoCount.get()); + assertEquals(yellCount1, Ext5Wrapper1.yellCount.get()); + assertEquals(yellCount2, Ext5Wrapper2.yellCount.get()); assertEquals("Ext5Impl2-yell", impl2.yell(url, "ha")); - assertEquals(echoCount1 + 1, Ext5AutoProxy1.echoCount.get()); - assertEquals(echoCount2 + 1, Ext5AutoProxy2.echoCount.get()); - assertEquals(yellCount1 + 1, Ext5AutoProxy1.yellCount.get()); - assertEquals(yellCount2 + 1, Ext5AutoProxy2.yellCount.get()); + assertEquals(echoCount1 + 1, Ext5Wrapper1.echoCount.get()); + assertEquals(echoCount2 + 1, Ext5Wrapper2.echoCount.get()); + assertEquals(yellCount1 + 1, Ext5Wrapper1.yellCount.get()); + assertEquals(yellCount2 + 1, Ext5Wrapper2.yellCount.get()); } @Test @@ -94,7 +94,7 @@ public class ExtensionLoaderTest { } @Test - public void test_getExtension_ExceptionNoExtension_NameOnAutoProxyNoAffact() throws Exception { + public void test_getExtension_ExceptionNoExtension_NameOnWrapperNoAffact() throws Exception { try { ExtensionLoader.getExtensionLoader(Ext5NoAdaptiveMethod.class).getExtension("XXX"); } catch (IllegalStateException expected) { @@ -193,6 +193,27 @@ public class ExtensionLoaderTest { assertEquals("url == null", e.getMessage()); } } + + @Test + public void test_getAdaptiveExtension_ExceptionWhenNoAdativeMethodOnInterface() throws Exception { + try { + ExtensionLoader.getExtensionLoader(Ext5NoAdaptiveMethod.class).getAdaptiveExtension(); + fail(); + } catch (IllegalStateException expected) { + assertThat(expected.getMessage(), + allOf(containsString("Can not create adaptive extenstion interface com.alibaba.dubbo.common.extensionloader.ext5.Ext5NoAdaptiveMethod"), + containsString("No adaptive method on extension com.alibaba.dubbo.common.extensionloader.ext5.Ext5NoAdaptiveMethod, refuse to create the adaptive class"))); + } + // 多次get,都会报错且相同 + try { + ExtensionLoader.getExtensionLoader(Ext5NoAdaptiveMethod.class).getAdaptiveExtension(); + fail(); + } catch (IllegalStateException expected) { + assertThat(expected.getMessage(), + allOf(containsString("Can not create adaptive extenstion interface com.alibaba.dubbo.common.extensionloader.ext5.Ext5NoAdaptiveMethod"), + containsString("No adaptive method on extension com.alibaba.dubbo.common.extensionloader.ext5.Ext5NoAdaptiveMethod, refuse to create the adaptive class"))); + } + } @Test public void test_getAdaptiveExtension_ExceptionWhenNotAdativeMethod() throws Exception { diff --git a/dubbo-common/src/test/java/com/alibaba/dubbo/common/extensionloader/ext5/impl/Ext5AutoProxy1.java b/dubbo-common/src/test/java/com/alibaba/dubbo/common/extensionloader/ext5/impl/Ext5Wrapper1.java similarity index 92% rename from dubbo-common/src/test/java/com/alibaba/dubbo/common/extensionloader/ext5/impl/Ext5AutoProxy1.java rename to dubbo-common/src/test/java/com/alibaba/dubbo/common/extensionloader/ext5/impl/Ext5Wrapper1.java index ebc05b9271..bd12a0fdb7 100644 --- a/dubbo-common/src/test/java/com/alibaba/dubbo/common/extensionloader/ext5/impl/Ext5AutoProxy1.java +++ b/dubbo-common/src/test/java/com/alibaba/dubbo/common/extensionloader/ext5/impl/Ext5Wrapper1.java @@ -25,14 +25,14 @@ import com.alibaba.dubbo.common.extensionloader.ext5.Ext5NoAdaptiveMethod; * @author ding.lid */ @Extension("XXX") -public class Ext5AutoProxy1 implements Ext5NoAdaptiveMethod { +public class Ext5Wrapper1 implements Ext5NoAdaptiveMethod { Ext5NoAdaptiveMethod instance; public static AtomicInteger echoCount = new AtomicInteger(); public static AtomicInteger yellCount = new AtomicInteger(); public static AtomicInteger bangCount = new AtomicInteger(); - public Ext5AutoProxy1(Ext5NoAdaptiveMethod instance) { + public Ext5Wrapper1(Ext5NoAdaptiveMethod instance) { this.instance = instance; } diff --git a/dubbo-common/src/test/java/com/alibaba/dubbo/common/extensionloader/ext5/impl/Ext5AutoProxy2.java b/dubbo-common/src/test/java/com/alibaba/dubbo/common/extensionloader/ext5/impl/Ext5Wrapper2.java similarity index 92% rename from dubbo-common/src/test/java/com/alibaba/dubbo/common/extensionloader/ext5/impl/Ext5AutoProxy2.java rename to dubbo-common/src/test/java/com/alibaba/dubbo/common/extensionloader/ext5/impl/Ext5Wrapper2.java index a5f3d30fb2..eb077d3db4 100644 --- a/dubbo-common/src/test/java/com/alibaba/dubbo/common/extensionloader/ext5/impl/Ext5AutoProxy2.java +++ b/dubbo-common/src/test/java/com/alibaba/dubbo/common/extensionloader/ext5/impl/Ext5Wrapper2.java @@ -23,14 +23,14 @@ import com.alibaba.dubbo.common.extensionloader.ext5.Ext5NoAdaptiveMethod; /** * @author ding.lid */ -public class Ext5AutoProxy2 implements Ext5NoAdaptiveMethod { +public class Ext5Wrapper2 implements Ext5NoAdaptiveMethod { Ext5NoAdaptiveMethod instance; public static AtomicInteger echoCount = new AtomicInteger(); public static AtomicInteger yellCount = new AtomicInteger(); public static AtomicInteger bangCount = new AtomicInteger(); - public Ext5AutoProxy2(Ext5NoAdaptiveMethod instance) { + public Ext5Wrapper2(Ext5NoAdaptiveMethod instance) { this.instance = instance; } diff --git a/dubbo-common/src/test/resources/META-INF/services/com.alibaba.dubbo.common.extensionloader.ext5.Ext5NoAdaptiveMethod b/dubbo-common/src/test/resources/META-INF/services/com.alibaba.dubbo.common.extensionloader.ext5.Ext5NoAdaptiveMethod index 8010ca6859..6b655f9fe0 100644 --- a/dubbo-common/src/test/resources/META-INF/services/com.alibaba.dubbo.common.extensionloader.ext5.Ext5NoAdaptiveMethod +++ b/dubbo-common/src/test/resources/META-INF/services/com.alibaba.dubbo.common.extensionloader.ext5.Ext5NoAdaptiveMethod @@ -1,4 +1,4 @@ com.alibaba.dubbo.common.extensionloader.ext5.impl.Ext5Impl1 com.alibaba.dubbo.common.extensionloader.ext5.impl.Ext5Impl2 -com.alibaba.dubbo.common.extensionloader.ext5.impl.Ext5AutoProxy1 -com.alibaba.dubbo.common.extensionloader.ext5.impl.Ext5AutoProxy2 \ No newline at end of file +com.alibaba.dubbo.common.extensionloader.ext5.impl.Ext5Wrapper1 +com.alibaba.dubbo.common.extensionloader.ext5.impl.Ext5Wrapper2 \ No newline at end of file