在Dubbo拦截器中拿到Invoker的引用对象
本文基于Dubbo 2.7.8。 当我们自定义Dubbo拦截器的时,有时候想要拿到代理对象(这里的代理对象是指Spring容器中的实际对象,可能已经被Cglib或Jdk代理),这里提供一种简单可行的方案。目前2.7.5及以上版本可用 先来看一下Dubbo服务导出的调用链: //导出所有服务 private void exportServices() { configManager.getServices().forEach(sc -> { // TODO, compatible with ServiceConfig.export() ServiceConfig serviceConfig = (ServiceConfig) sc; serviceConfig.setBootstrap(this); if (exportAsync) { ExecutorService executor = executorRepository.getServiceExporterExecutor(); Future<?> future = executor.submit(() -> { sc.export(); exportedServices.add(sc); }); asyncExportingFutures.add(future); } else { sc.export(); exportedServices.add(sc); } }); } //单个服务导出 public synchronized void export() //是否需要导出 if (!shouldExport()) { return; } checkAndUpdateSubConfigs(); doExport(); exported(); } protected synchronized void doExport() { if (exported) { return; } exported = true; if (StringUtils.isEmpty(path)) { path = interfaceName; } doExportUrls(); } private void doExportUrls() { //这里是重点 ServiceRepository repository = ApplicationModel.getServiceRepository(); ServiceDescriptor serviceDescriptor = repository.registerService(getInterfaceClass()); repository.registerProvider( getUniqueServiceName(), ref, serviceDescriptor, this, serviceMetadata ); } //注册提供者 public void registerProvider(String serviceKey, Object serviceInstance, ServiceDescriptor serviceModel, ServiceConfigBase<?> serviceConfig, ServiceMetadata serviceMetadata) { ProviderModel providerModel = new ProviderModel(serviceKey, serviceInstance, serviceModel, serviceConfig, serviceMetadata); //key为serviceKey providers.putIfAbsent(serviceKey, providerModel); providersWithoutGroup.putIfAbsent(keyWithoutGroup(serviceKey), providerModel); } 可以看到在Dubbo服务导出的时候会向ServiceRepository注册服务信息,而我们在Filter中可以通过Invocation的getTargetServiceUniqueName拿到serviceKey。 结果显而易见: 直接通过以下方式就可以拿到代理对象: ProviderModel providerModel = ApplicationModel.getServiceRepository().lookupExportedService(invocation.getTargetServiceUniqueName()); System.out.println(providerModel.getServiceInstance().getClass()); 怎么样是不是很简单,如果有其它需求从ServiceRepository中也可以很方便的拿到其他一些类和方法相关的信息。