- AdaptiveInstance创建后,之后的getAdaptiveInstance不再去调用createAdaptiveClass方法
- UT添加 git-svn-id: http://code.alibabatech.com/svn/dubbo/trunk@37 1a56cb94-b969-4eaa-88fa-be21384802f2
This commit is contained in:
parent
bffa027df5
commit
7f32ab5a75
|
|
@ -72,6 +72,7 @@ public class ExtensionLoader<T> {
|
|||
private volatile Class<?> cachedAdaptiveClass = null;
|
||||
|
||||
private final Reference<Object> cachedAdaptiveInstance = new Reference<Object>();
|
||||
private volatile Throwable createAdaptiveInstanceError;
|
||||
|
||||
private Set<Class<?>> cachedWrapperClasses;
|
||||
|
||||
|
|
@ -135,17 +136,35 @@ public class ExtensionLoader<T> {
|
|||
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<T> {
|
|||
} else {
|
||||
try {
|
||||
clazz.getConstructor(type);
|
||||
Set<Class<?>> autoproxies = cachedWrapperClasses;
|
||||
if (autoproxies == null) {
|
||||
Set<Class<?>> wrappers = cachedWrapperClasses;
|
||||
if (wrappers == null) {
|
||||
cachedWrapperClasses = new ConcurrentHashSet<Class<?>>();
|
||||
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<T> {
|
|||
}
|
||||
// 完全没有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<T> {
|
|||
return classLoader;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return this.getClass().getName() + "[" + type.getName() + "]";
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
@ -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
|
||||
com.alibaba.dubbo.common.extensionloader.ext5.impl.Ext5Wrapper1
|
||||
com.alibaba.dubbo.common.extensionloader.ext5.impl.Ext5Wrapper2
|
||||
Loading…
Reference in New Issue