private String exportOrUnexportCallbackService()

in dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/CallbackServiceCodec.java [123:214]


    private String exportOrUnexportCallbackService(
            Channel channel, RpcInvocation inv, URL url, Class clazz, Object inst, Boolean export) throws IOException {
        int instid = System.identityHashCode(inst);

        Map<String, String> params = new HashMap<>(3);
        // no need to new client again
        params.put(IS_SERVER_KEY, Boolean.FALSE.toString());
        // mark it's a callback, for troubleshooting
        params.put(IS_CALLBACK_SERVICE, Boolean.TRUE.toString());
        String group = (inv == null ? null : (String) inv.getObjectAttachmentWithoutConvert(GROUP_KEY));
        if (group != null && group.length() > 0) {
            params.put(GROUP_KEY, group);
        }
        // add method, for verifying against method, automatic fallback (see dubbo protocol)
        params.put(METHODS_KEY, StringUtils.join(ClassUtils.getDeclaredMethodNames(clazz), ","));

        Map<String, String> tmpMap = new HashMap<>();
        if (url != null) {
            Map<String, String> parameters = url.getParameters();
            if (parameters != null && !parameters.isEmpty()) {
                tmpMap.putAll(parameters);
            }
        }
        tmpMap.putAll(params);

        tmpMap.remove(VERSION_KEY); // doesn't need to distinguish version for callback
        tmpMap.remove(Constants.BIND_PORT_KEY); // callback doesn't needs bind.port
        tmpMap.put(INTERFACE_KEY, clazz.getName());
        URL exportUrl = new ServiceConfigURL(
                DubboProtocol.NAME,
                channel.getLocalAddress().getAddress().getHostAddress(),
                channel.getLocalAddress().getPort(),
                clazz.getName() + "." + instid,
                tmpMap);

        // no need to generate multiple exporters for different channel in the same JVM, cache key cannot collide.
        String cacheKey = getClientSideCallbackServiceCacheKey(instid);
        String countKey = getClientSideCountKey(clazz.getName());
        if (export) {
            // one channel can have multiple callback instances, no need to re-export for different instance.
            if (!channel.hasAttribute(cacheKey)) {
                if (!isInstancesOverLimit(channel, url, clazz.getName(), instid, false)) {
                    ModuleModel moduleModel;
                    if (inv.getServiceModel() == null) {
                        // TODO should get scope model from url?
                        moduleModel = ApplicationModel.defaultModel().getDefaultModule();
                        logger.error(
                                PROTOCOL_FAILED_LOAD_MODEL,
                                "",
                                "",
                                "Unable to get Service Model from Invocation. Please check if your invocation failed! "
                                        + "This error only happen in UT cases! Invocation:" + inv);
                    } else {
                        moduleModel = inv.getServiceModel().getModuleModel();
                    }

                    ServiceDescriptor serviceDescriptor =
                            moduleModel.getServiceRepository().registerService(clazz);
                    ServiceMetadata serviceMetadata = new ServiceMetadata(
                            clazz.getName() + "." + instid, exportUrl.getGroup(), exportUrl.getVersion(), clazz);
                    String serviceKey =
                            BaseServiceMetadata.buildServiceKey(exportUrl.getPath(), group, exportUrl.getVersion());
                    ProviderModel providerModel = new ProviderModel(
                            serviceKey,
                            inst,
                            serviceDescriptor,
                            moduleModel,
                            serviceMetadata,
                            ClassUtils.getClassLoader(clazz));
                    moduleModel.getServiceRepository().registerProvider(providerModel);

                    exportUrl = exportUrl.setScopeModel(moduleModel);
                    exportUrl = exportUrl.setServiceModel(providerModel);
                    Invoker<?> invoker = proxyFactory.getInvoker(inst, clazz, exportUrl);
                    // should destroy resource?
                    Exporter<?> exporter = protocolSPI.export(invoker);
                    // this is used for tracing if instid has published service or not.
                    channel.setAttribute(cacheKey, exporter);
                    logger.info("Export a callback service :" + exportUrl + ", on " + channel + ", url is: " + url);
                    increaseInstanceCount(channel, countKey);
                }
            }
        } else {
            if (channel.hasAttribute(cacheKey)) {
                Exporter<?> exporter = (Exporter<?>) channel.getAttribute(cacheKey);
                exporter.unexport();
                channel.removeAttribute(cacheKey);
                decreaseInstanceCount(channel, countKey);
            }
        }
        return String.valueOf(instid);
    }