fixes #10012
This commit is contained in:
parent
fe2d7dcd04
commit
d0ae161635
|
|
@ -187,7 +187,15 @@ public abstract class AbstractInterfaceConfig extends AbstractMethodConfig {
|
|||
|
||||
protected String tag;
|
||||
|
||||
private Boolean auth;
|
||||
private Boolean auth;
|
||||
|
||||
/*Indicates to create separate instances or not for services/references that have the same serviceKey.
|
||||
* By default, all services/references that have the same serviceKey will share the same instance and process.
|
||||
*
|
||||
* This key currently can only work when using ReferenceConfig and SimpleReferenceCache together.
|
||||
* Call ReferenceConfig.get() directly will not check this attribute.
|
||||
*/
|
||||
private Boolean singleton;
|
||||
|
||||
public AbstractInterfaceConfig() {
|
||||
}
|
||||
|
|
@ -855,14 +863,22 @@ public abstract class AbstractInterfaceConfig extends AbstractMethodConfig {
|
|||
public SslConfig getSslConfig() {
|
||||
return getConfigManager().getSsl().orElse(null);
|
||||
}
|
||||
|
||||
|
||||
public Boolean getSingleton() {
|
||||
return singleton;
|
||||
}
|
||||
|
||||
public void setSingleton(Boolean singleton) {
|
||||
this.singleton = singleton;
|
||||
}
|
||||
|
||||
protected void initServiceMetadata(AbstractInterfaceConfig interfaceConfig) {
|
||||
serviceMetadata.setVersion(getVersion(interfaceConfig));
|
||||
serviceMetadata.setGroup(getGroup(interfaceConfig));
|
||||
serviceMetadata.setDefaultGroup(getGroup(interfaceConfig));
|
||||
serviceMetadata.setServiceInterfaceName(getInterface());
|
||||
}
|
||||
|
||||
|
||||
public String getGroup(AbstractInterfaceConfig interfaceConfig) {
|
||||
return StringUtils.isEmpty(getGroup()) ? (interfaceConfig != null ? interfaceConfig.getGroup() : getGroup()) : getGroup();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,6 +18,8 @@ package org.apache.dubbo.config.utils;
|
|||
|
||||
import org.apache.dubbo.common.BaseServiceMetadata;
|
||||
import org.apache.dubbo.common.config.ReferenceCache;
|
||||
import org.apache.dubbo.common.logger.Logger;
|
||||
import org.apache.dubbo.common.logger.LoggerFactory;
|
||||
import org.apache.dubbo.common.utils.CollectionUtils;
|
||||
import org.apache.dubbo.common.utils.StringUtils;
|
||||
import org.apache.dubbo.config.ReferenceConfigBase;
|
||||
|
|
@ -40,6 +42,7 @@ import java.util.concurrent.atomic.AtomicInteger;
|
|||
* You can implement and use your own {@link ReferenceConfigBase} cache if you need use complicate strategy.
|
||||
*/
|
||||
public class SimpleReferenceCache implements ReferenceCache {
|
||||
private static final Logger logger = LoggerFactory.getLogger(SimpleReferenceCache.class);
|
||||
public static final String DEFAULT_NAME = "_DEFAULT_";
|
||||
/**
|
||||
* Create the key with the <b>Group</b>, <b>Interface</b> and <b>version</b> attribute of {@link ReferenceConfigBase}.
|
||||
|
|
@ -107,15 +110,26 @@ public class SimpleReferenceCache implements ReferenceCache {
|
|||
public <T> T get(ReferenceConfigBase<T> rc) {
|
||||
String key = generator.generateKey(rc);
|
||||
Class<?> type = rc.getInterfaceClass();
|
||||
Object proxy = references.computeIfAbsent(rc, _rc -> {
|
||||
|
||||
boolean singleton = rc.getSingleton() == null || rc.getSingleton();
|
||||
T proxy = null;
|
||||
// Check existing proxy of the same 'key' and 'type' first.
|
||||
if (singleton) {
|
||||
proxy = get(key, (Class<T>) type);
|
||||
} else {
|
||||
logger.warn("Using non-singleton ReferenceConfig and ReferenceCache at the same time may cause memory leak. " +
|
||||
"Call ReferenceConfig#get() directly for non-singleton ReferenceConfig instead of using ReferenceCache#get(ReferenceConfig)");
|
||||
}
|
||||
|
||||
if (proxy == null) {
|
||||
List<ReferenceConfigBase<?>> referencesOfType = referenceTypeMap.computeIfAbsent(type, _t -> Collections.synchronizedList(new ArrayList<>()));
|
||||
referencesOfType.add(rc);
|
||||
List<ReferenceConfigBase<?>> referenceConfigList = referenceKeyMap.computeIfAbsent(key, _k -> Collections.synchronizedList(new ArrayList<>()));
|
||||
referenceConfigList.add(rc);
|
||||
return _rc.get();
|
||||
});
|
||||
proxy = rc.get();
|
||||
}
|
||||
|
||||
return (T) proxy;
|
||||
return proxy;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -138,6 +152,13 @@ public class SimpleReferenceCache implements ReferenceCache {
|
|||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check and return existing ReferenceConfig and its corresponding proxy instance.
|
||||
*
|
||||
* @param key ServiceKey
|
||||
* @param <T> service interface type
|
||||
* @return the existing proxy instance of the same service key
|
||||
*/
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> T get(String key) {
|
||||
|
|
@ -162,6 +183,13 @@ public class SimpleReferenceCache implements ReferenceCache {
|
|||
return Collections.unmodifiableList(proxiesOfType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check and return existing ReferenceConfig and its corresponding proxy instance.
|
||||
*
|
||||
* @param type service interface class
|
||||
* @param <T> service interface type
|
||||
* @return the existing proxy instance of the same interface definition
|
||||
*/
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> T get(Class<T> type) {
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ import org.junit.jupiter.api.BeforeEach;
|
|||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
public class ReferenceCacheTest {
|
||||
|
|
@ -42,16 +43,18 @@ public class ReferenceCacheTest {
|
|||
ReferenceCache cache = SimpleReferenceCache.getCache();
|
||||
MockReferenceConfig config = buildMockReferenceConfig("org.apache.dubbo.config.utils.service.FooService", "group1", "1.0.0");
|
||||
assertEquals(0L, config.getCounter());
|
||||
cache.get(config);
|
||||
Object proxy = cache.get(config);
|
||||
assertTrue(config.isGetMethodRun());
|
||||
|
||||
// singleton reference config by default
|
||||
MockReferenceConfig configCopy = buildMockReferenceConfig("org.apache.dubbo.config.utils.service.FooService", "group1", "1.0.0");
|
||||
assertEquals(1L, configCopy.getCounter());
|
||||
cache.get(configCopy);
|
||||
assertTrue(configCopy.isGetMethodRun());
|
||||
Object proxyOfCopyConfig = cache.get(configCopy);
|
||||
assertFalse(configCopy.isGetMethodRun());
|
||||
|
||||
assertEquals(2L, config.getCounter());
|
||||
assertEquals(2L, configCopy.getCounter());
|
||||
assertEquals(1L, config.getCounter());
|
||||
assertEquals(1L, configCopy.getCounter());
|
||||
assertEquals(proxy, proxyOfCopyConfig);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
|||
Loading…
Reference in New Issue