- 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:
ding.lid 2011-10-21 07:41:44 +00:00
parent bffa027df5
commit 7f32ab5a75
5 changed files with 80 additions and 35 deletions

View File

@ -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() + "]";
}
}

View File

@ -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 {

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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