现在系统的又独立的支付应用,收到第三方支付(微信/支付宝)支付结果后,该服务需要将支付结果的通知下发给发起支付的各个子应用。 现在是定义了一个公共的接口,每个子应用都去实现它,但是这种方式非常麻烦,假如后面子应用越来越多,岂不是要在xml里面配置很多实现类? 有没有可能动态获取这个接口的所有实现类,然后循环执行?
现在系统的又独立的支付应用,收到第三方支付(微信/支付宝)支付结果后,该服务需要将支付结果的通知下发给发起支付的各个子应用。 现在是定义了一个公共的接口,每个子应用都去实现它,但是这种方式非常麻烦,假如后面子应用越来越多,岂不是要在xml里面配置很多实现类? 有没有可能动态获取这个接口的所有实现类,然后循环执行?
这是最简单的方式,也不复杂。如果要动态获取的话,可以将实现了这个接口的类注册到zookeeper上,然后支付应用获取调用,不过太麻烦了,而且不了解zookeeper的话很容易出问题,没必要引入这么多复杂性
private void init() {
// 避免重复初始化
if (initialized) {
return;
}
initialized = true;
// 检查接口名称是否为空
if (interfaceName == null || interfaceName.length() == 0) {
throw new IllegalStateException("<dubbo:reference interface=\"\" /> interface not allow null!");
}
// 获取消费者全局配置
checkDefault();
appendProperties(this);
if (getGeneric() == null && getConsumer() != null) {
setGeneric(getConsumer().getGeneric()); // 利用ConsumerConfig配置范型
}
// 如果是范型接口,则interfacesClass的类型是GenericService
if (ProtocolUtils.isGeneric(getGeneric())) {
interfaceClass = GenericService.class;
} else {
try {
interfaceClass = Class.forName(interfaceName, true, Thread.currentThread()
.getContextClassLoader());
} catch (ClassNotFoundException e) {
throw new IllegalStateException(e.getMessage(), e);
}
// 检查接口,以及检查接口中是否有此方法
checkInterfaceAndMethods(interfaceClass, methods);
}
String resolve = System.getProperty(interfaceName);
String resolveFile = null;
// 如果服务比较多,可以指定dubbo-resolve.properties文件配置service(service集中配置文件)
if (resolve == null || resolve.length() == 0) {
resolveFile = System.getProperty("dubbo.resolve.file");
if (resolveFile == null || resolveFile.length() == 0) {
File userResolveFile = new File(new File(System.getProperty("user.home")), "dubbo-resolve.properties");
if (userResolveFile.exists()) {
resolveFile = userResolveFile.getAbsolutePath();
}
}
if (resolveFile != null && resolveFile.length() > 0) {
Properties properties = new Properties();
FileInputStream fis = null;
try {
fis = new FileInputStream(new File(resolveFile));
properties.load(fis);
} catch (IOException e) {
throw new IllegalStateException("Unload " + resolveFile + ", cause: " + e.getMessage(), e);
} finally {
try {
if(null != fis) fis.close();
} catch (IOException e) {
logger.warn(e.getMessage(), e);
}
}
resolve = properties.getProperty(interfaceName);
}
}
if (resolve != null && resolve.length() > 0) {
url = resolve;
if (logger.isWarnEnabled()) {
if (resolveFile != null && resolveFile.length() > 0) {
logger.warn("Using default dubbo resolve file " + resolveFile + " replace " + interfaceName + "" + resolve + " to p2p invoke remote service.");
} else {
logger.warn("Using -D" + interfaceName + "=" + resolve + " to p2p invoke remote service.");
}
}
}
// 如果application module registries monitor未配置,则使用consumer的
if (consumer != null) {
if (application == null) {
application = consumer.getApplication();
}
if (module == null) {
module = consumer.getModule();
}
if (registries == null) {
registries = consumer.getRegistries();
}
if (monitor == null) {
monitor = consumer.getMonitor();
}
}
// 如果module已关联,则关联module的registries和monitor
if (module != null) {
if (registries == null) {
registries = module.getRegistries();
}
if (monitor == null) {
monitor = module.getMonitor();
}
}
// 如果application已关联,则关联application的registries和monitor
if (application != null) {
if (registries == null) {
registries = application.getRegistries();
}
if (monitor == null) {
monitor = application.getMonitor();
}
}
checkApplication();
// 检查远端和本地服务接口真实存在(是否可load
checkStubAndMock(interfaceClass);
Map<String, String> map = new HashMap<String, String>();
// 配置dubbo的端属性(是consumer还是provider)、版本、创建时间、进程号
Map<Object, Object> attributes = new HashMap<Object, Object>();
map.put(Constants.SIDE_KEY, Constants.CONSUMER_SIDE);
map.put(Constants.DUBBO_VERSION_KEY, Version.getVersion());
map.put(Constants.TIMESTAMP_KEY, String.valueOf(System.currentTimeMillis()));
if (ConfigUtils.getPid() > 0) {
map.put(Constants.PID_KEY, String.valueOf(ConfigUtils.getPid()));
}
// 非范型
if (! isGeneric()) {
String revision = Version.getVersion(interfaceClass, version);
if (revision != null && revision.length() > 0) {
map.put("revision", revision);
}
String[] methods = Wrapper.getWrapper(interfaceClass).getMethodNames();
if(methods.length == 0) {
logger.warn("NO method found in service interface " + interfaceClass.getName());
map.put("methods", Constants.ANY_VALUE);
}
else {
map.put("methods", StringUtils.join(new HashSet<String>(Arrays.asList(methods)), ","));
}
}
map.put(Constants.INTERFACE_KEY, interfaceName);
appendParameters(map, application);
appendParameters(map, module);
appendParameters(map, consumer, Constants.DEFAULT_KEY);
appendParameters(map, this);
String prifix = StringUtils.getServiceKey(map);
if (methods != null && methods.size() > 0) {
for (MethodConfig method : methods) {
appendParameters(map, method, method.getName());
String retryKey = method.getName() + ".retry";
if (map.containsKey(retryKey)) {
String retryValue = map.remove(retryKey);
if ("false".equals(retryValue)) {
map.put(method.getName() + ".retries", "0");
}
}
appendAttributes(attributes, method, prifix + "." + method.getName());
checkAndConvertImplicitConfig(method, map, attributes);
}
}
//attributes通过系统context进行存储.
StaticContext.getSystemContext().putAll(attributes);
ref = createProxy(map);
}
12 回答5.9k 阅读
2 回答3.2k 阅读✓ 已解决
3 回答6.9k 阅读✓ 已解决
3 回答3k 阅读✓ 已解决
5 回答4.6k 阅读
4 回答2.3k 阅读
3 回答4.5k 阅读
可以使用2种方法,一种是基于url来获取到对应的Dubbo服务。
另外一种是通过group来区分接口的不同实现,可扩展性,适用性会更好。
贴段简单的代码,具体的实现可以看这篇文章:Dubbo动态获取接口实现,和这个Demo项目dubbo-dynamic-impl