文档章节

dubbo源码分析-服务导出(一)

秦帝国三川郡守
 秦帝国三川郡守
发布于 02/19 19:33
字数 5740
阅读 16
收藏 0

简介

dubbo框架spring Schema扩展机制与Spring集成,在spring初始化时候加载dubbo的配置类。 dubbo服务导出的入口类是ServiceBeanonApplicationEvent方法 ServiceBean的继承关系如下 ServiceBean

public class ServiceBean<T> extends ServiceConfig<T> implements InitializingBean, DisposableBean, ApplicationContextAware, ApplicationListener<ContextRefreshedEvent>, BeanNameAware {
    private static final long serialVersionUID = 213195494150089726L;
    private static transient ApplicationContext SPRING_CONTEXT;
    private final transient Service service;
    private transient ApplicationContext applicationContext;
    private transient String beanName;
    private transient boolean supportedApplicationListener;

    public ServiceBean() {
        this.service = null;
    }

    public ServiceBean(Service service) {
        super(service);
        this.service = service;
    }

    public static ApplicationContext getSpringContext() {
        return SPRING_CONTEXT;
    }

    public void setApplicationContext(ApplicationContext applicationContext) {
        this.applicationContext = applicationContext;
        SpringExtensionFactory.addApplicationContext(applicationContext);
        if (applicationContext != null) {
            SPRING_CONTEXT = applicationContext;

            try {
                Method method = applicationContext.getClass().getMethod("addApplicationListener", ApplicationListener.class);
                method.invoke(applicationContext, this);
                this.supportedApplicationListener = true;
            } catch (Throwable var5) {
                if (applicationContext instanceof AbstractApplicationContext) {
                    try {
                        Method method = AbstractApplicationContext.class.getDeclaredMethod("addListener", ApplicationListener.class);
                        if (!method.isAccessible()) {
                            method.setAccessible(true);
                        }

                        method.invoke(applicationContext, this);
                        this.supportedApplicationListener = true;
                    } catch (Throwable var4) {
                        ;
                    }
                }
            }
        }

    }

    public void setBeanName(String name) {
        this.beanName = name;
    }

    public Service getService() {
        return this.service;
    }

    public void onApplicationEvent(ContextRefreshedEvent event) {
	//如果不延迟导出且exported和unexported都为false 执行导出
        if (this.isDelay() && !this.isExported() && !this.isUnexported()) {
            if (logger.isInfoEnabled()) {
                logger.info("The service ready on spring started. service: " + this.getInterface());
            }

            this.export();
        }

    }

    private boolean isDelay() {
   //调用父类`AbstractServiceConfig`中方法
        Integer delay = this.getDelay();
        ProviderConfig provider = this.getProvider();
        if (delay == null && provider != null) {
   //调用父类`AbstractServiceConfig`中getDelay方法
            delay = provider.getDelay();
        }
     //delay == -1表示不需要延迟导出
        return this.supportedApplicationListener && (delay == null || delay == -1);
    }
}

public ProviderConfig getProvider() {
        return this.provider;
    }

supportedApplicationListener 变量含义,该变量用于表示当前的 Spring 容器是否支持 ApplicationListener,这个值初始为 false。在 Spring 容器将自己设置到 ServiceBean 中时,ServiceBean 的 setApplicationContext 方法会检测 Spring 容器是否支持 ApplicationListener。若支持,则将 supportedApplicationListener 置为 true。

this.export()调用ServiceConfig中方法

public synchronized void export() {
//如果provider存在,从provider中取export和delay属性
        if (this.provider != null) {
            if (this.export == null) {
                this.export = this.provider.getExport();
            }

            if (this.delay == null) {
                this.delay = this.provider.getDelay();
            }
        }
		//如果未导出 判断delay决定立即导出 还是延迟导出
        if (this.export == null || this.export) {
            if (this.delay != null && this.delay > 0) {
                delayExportExecutor.schedule(new Runnable() {
                    public void run() {
                        ServiceConfig.this.doExport();
                    }
                }, (long)this.delay, TimeUnit.MILLISECONDS);
            } else {
                this.doExport();
            }

        }
    }

doExport

protected synchronized void doExport() {
        if (this.unexported) {
            throw new IllegalStateException("Already unexported!");
        } else if (!this.exported) {
            this.exported = true;
            if (this.interfaceName != null && this.interfaceName.length() != 0) {
                this.checkDefault();
                if (this.provider != null) {
                    if (this.application == null) {
                        this.application = this.provider.getApplication();
                    }

                    if (this.module == null) {
                        this.module = this.provider.getModule();
                    }

                    if (this.registries == null) {
                        this.registries = this.provider.getRegistries();
                    }

                    if (this.monitor == null) {
                        this.monitor = this.provider.getMonitor();
                    }

                    if (this.protocols == null) {
                        this.protocols = this.provider.getProtocols();
                    }
                }

                if (this.module != null) {
                    if (this.registries == null) {
                        this.registries = this.module.getRegistries();
                    }

                    if (this.monitor == null) {
                        this.monitor = this.module.getMonitor();
                    }
                }

                if (this.application != null) {
                    if (this.registries == null) {
                        this.registries = this.application.getRegistries();
                    }

                    if (this.monitor == null) {
                        this.monitor = this.application.getMonitor();
                    }
                }
				 // 检测 ref 是否为泛化服务类型
                if (this.ref instanceof GenericService) {
                    this.interfaceClass = GenericService.class;
                    if (StringUtils.isEmpty(this.generic)) {
					// 设置 generic = "true"
                        this.generic = Boolean.TRUE.toString();
                    }
                } else {
                    try {
                        this.interfaceClass = Class.forName(this.interfaceName, true, Thread.currentThread().getContextClassLoader());
                    } catch (ClassNotFoundException var5) {
                        throw new IllegalStateException(var5.getMessage(), var5);
                    }
					//检查接口中是否有MethodConfig中定义的方法名称,没有抛异常
                    this.checkInterfaceAndMethods(this.interfaceClass, this.methods);
					//检查ref类型是否合法
                    this.checkRef();
					// 设置 generic = "true"
                    this.generic = Boolean.FALSE.toString();
                }
				//如果loal = true 或stub = true 加载并检查本地实现是否合法
                Class stubClass;
                if (this.local != null) {
                    if ("true".equals(this.local)) {
                        this.local = this.interfaceName + "Local";
                    }

                    try {
                        stubClass = ClassHelper.forNameWithThreadContextClassLoader(this.local);
                    } catch (ClassNotFoundException var4) {
                        throw new IllegalStateException(var4.getMessage(), var4);
                    }

                    if (!this.interfaceClass.isAssignableFrom(stubClass)) {
                        throw new IllegalStateException("The local implementation class " + stubClass.getName() + " not implement interface " + this.interfaceName);
                    }
                }

                if (this.stub != null) {
                    if ("true".equals(this.stub)) {
                        this.stub = this.interfaceName + "Stub";
                    }

                    try {
                        stubClass = ClassHelper.forNameWithThreadContextClassLoader(this.stub);
                    } catch (ClassNotFoundException var3) {
                        throw new IllegalStateException(var3.getMessage(), var3);
                    }

                    if (!this.interfaceClass.isAssignableFrom(stubClass)) {
                        throw new IllegalStateException("The stub implementation class " + stubClass.getName() + " not implement interface " + this.interfaceName);
                    }
                }
				// 检测各种对象是否为空,为空则新建,或者抛出异常
				//检查dubbo.application.name 设置系统属性dubbo.service.shutdown.wait和dubbo.service.shutdown.wait.seconds
                this.checkApplication(); 
				//检查RegistryConfig并使用set方法反射设置属性(先从系统属性中取)
                this.checkRegistry();
				//设置ProtocalConfig并使用set方法反射设置属性(先从系统属性中取)
                this.checkProtocol();
				//设置当前ServiceConfig并使用set方法反射设置属性(先从系统属性中取)
                appendProperties(this);
                this.checkStubAndMock(this.interfaceClass);
                if (this.path == null || this.path.length() == 0) {
                    this.path = this.interfaceName;
                }

                this.doExportUrls();
				 // ProviderModel 表示服务提供者模型,此对象中存储了与服务提供者相关的信息。
    			// 比如服务的配置信息,服务实例等。每个被导出的服务对应一个 ProviderModel。
    			// ApplicationModel 持有所有的 ProviderModel。
                ProviderModel providerModel = new ProviderModel(this.getUniqueServiceName(), this, this.ref);
                ApplicationModel.initProviderModel(this.getUniqueServiceName(), providerModel);
            } else {
                throw new IllegalStateException("<dubbo:service interface=\"\" /> interface not allow null!");
            }
        }
    }
	//检查接口类型是否合法
	//遍历MethodConfig中方法,检查接口中是否有MethodConfig中定义的方法名称,没有抛异常
	protected void checkInterfaceAndMethods(Class<?> interfaceClass, List<MethodConfig> methods) {
        if (interfaceClass == null) {
            throw new IllegalStateException("interface not allow null!");
        } else if (!interfaceClass.isInterface()) {
            throw new IllegalStateException("The interface class " + interfaceClass + " is not a interface!");
        } else {
            if (methods != null && methods.size() > 0) {
                Iterator i$ = methods.iterator();

                while(i$.hasNext()) {
                    MethodConfig methodBean = (MethodConfig)i$.next();
                    String methodName = methodBean.getName();
                    if (methodName == null || methodName.length() == 0) {
                        throw new IllegalStateException("<dubbo:method> name attribute is required! Please check: <dubbo:service interface=\"" + interfaceClass.getName() + "\" ... ><dubbo:method name=\"\" ... /></<dubbo:reference>");
                    }

                    boolean hasMethod = false;
                    Method[] arr$ = interfaceClass.getMethods();
                    int len$ = arr$.length;

                    for(int i$ = 0; i$ < len$; ++i$) {
                        Method method = arr$[i$];
                        if (method.getName().equals(methodName)) {
                            hasMethod = true;
                            break;
                        }
                    }

                    if (!hasMethod) {
                        throw new IllegalStateException("The interface " + interfaceClass.getName() + " not found method " + methodName);
                    }
                }
            }

        }
    }
	//检查ref类型是否合法
	 private void checkRef() {
        if (this.ref == null) {
            throw new IllegalStateException("ref not allow null!");
        } else if (!this.interfaceClass.isInstance(this.ref)) {
            throw new IllegalStateException("The class " + this.ref.getClass().getName() + " unimplemented interface " + this.interfaceClass + "!");
        }
    }

doExportUrls

loadRegistries 加载注册中心链接,然后再遍历 ProtocolConfig 集合导出每个服务。并在导出服务的过程中,将服务注册到注册中心。 loadRegistries 方法主要包含如下的逻辑: 检测是否存在注册中心配置类,不存在则抛出异常 构建参数映射集合,也就是 map 构建注册中心链接列表 遍历链接列表,并根据条件决定是否将其添加到 registryList 中

private void doExportUrls() {
        List<URL> registryURLs = this.loadRegistries(true);
        Iterator i$ = this.protocols.iterator();

        while(i$.hasNext()) {
            ProtocolConfig protocolConfig = (ProtocolConfig)i$.next();
            this.doExportUrlsFor1Protocol(protocolConfig, registryURLs);
        }

    }
	
protected List<URL> loadRegistries(boolean provider) {
		//检查注册中心配置
        this.checkRegistry();
        List<URL> registryList = new ArrayList();
        if (this.registries != null && this.registries.size() > 0) {
            Iterator i$ = this.registries.iterator();

            label75:
            while(true) {
                RegistryConfig config;
                String address;
                do {
                    do {
                        do {
                            if (!i$.hasNext()) {
                                return registryList;
                            }

                            config = (RegistryConfig)i$.next();
                            address = config.getAddress();
							// 若 address 为空,则将其设为 0.0.0.0
                            if (address == null || address.length() == 0) {
                                address = "0.0.0.0";
                            }
							 // 从系统属性中加载注册中心地址
                            String sysaddress = System.getProperty("dubbo.registry.address");
                            if (sysaddress != null && sysaddress.length() > 0) {
                                address = sysaddress;
                            }
                        } while(address == null);
                    } while(address.length() <= 0);
                } while("N/A".equalsIgnoreCase(address));

                Map<String, String> map = new HashMap();
				 // 添加 ApplicationConfig 中的字段信息到 map 中
                appendParameters(map, this.application);
				 // 添加 RegistryConfig 字段信息到 map 中
                appendParameters(map, config);
				 // 添加 path、pid,protocol 等信息到 map 中
                map.put("path", RegistryService.class.getName());
                map.put("dubbo", Version.getVersion());
                map.put("timestamp", String.valueOf(System.currentTimeMillis()));
                if (ConfigUtils.getPid() > 0) {
                    map.put("pid", String.valueOf(ConfigUtils.getPid()));
                }

                if (!map.containsKey("protocol")) {
                    if (ExtensionLoader.getExtensionLoader(RegistryFactory.class).hasExtension("remote")) {
                        map.put("protocol", "remote");
                    } else {
                        map.put("protocol", "dubbo");
                    }
                }
				// 解析得到 URL 列表,address 可能包含多个注册中心 ip,
                // 因此解析得到的是一个 URL 列表
                List<URL> urls = UrlUtils.parseURLs(address, map);
                Iterator i$ = urls.iterator();

                while(true) {
                    URL url;
                    do {
                        if (!i$.hasNext()) {
                            continue label75;
                        }

                        url = (URL)i$.next();
                        url = url.addParameter("registry", url.getProtocol());
						 // 将 URL 协议头设置为 registry
                        url = url.setProtocol("registry");
                    } while((!provider || !url.getParameter("register", true)) && (provider || !url.getParameter("subscribe", true)));

                    registryList.add(url);
                }
            }
        } else {
            return registryList;
        }
    }
//解析address 如果address以;或|符号分隔 则拆分后解析 返回List<URL>
 public static List<URL> parseURLs(String address, Map<String, String> defaults) {
        if (address != null && address.length() != 0) {
            String[] addresses = Constants.REGISTRY_SPLIT_PATTERN.split(address);
            if (addresses != null && addresses.length != 0) {
                List<URL> registries = new ArrayList();
                String[] arr$ = addresses;
                int len$ = addresses.length;

                for(int i$ = 0; i$ < len$; ++i$) {
                    String addr = arr$[i$];
                    registries.add(parseURL(addr, defaults));
                }

                return registries;
            } else {
                return null;
            }
        } else {
            return null;
        }
    }

	public static URL parseURL(String address, Map<String, String> defaults) {
        if (address != null && address.length() != 0) {
            String url;
			//1 如果包含:// 直接返回url
			//2 否则用,拆分成address数组 后拼接url
			// 以172.19.103.55:2181,172.19.103.57:2181,172.19.103.54:2181为例
			// 返回172.19.103.55:2181?backup=172.19.103.57:2181,172.19.103.54:2181
            if (address.indexOf("://") >= 0) {
                url = address;
            } else {
                String[] addresses = Constants.COMMA_SPLIT_PATTERN.split(address);
                url = addresses[0];
                if (addresses.length > 1) {
                    StringBuilder backup = new StringBuilder();

                    for(int i = 1; i < addresses.length; ++i) {
                        if (i > 1) {
                            backup.append(",");
                        }

                        backup.append(addresses[i]);
                    }

                    url = url + "?backup=" + backup.toString();
                }
            }

            String defaultProtocol = defaults == null ? null : (String)defaults.get("protocol");
            if (defaultProtocol == null || defaultProtocol.length() == 0) {
                defaultProtocol = "dubbo";
            }

            String defaultUsername = defaults == null ? null : (String)defaults.get("username");
            String defaultPassword = defaults == null ? null : (String)defaults.get("password");
            int defaultPort = StringUtils.parseInteger(defaults == null ? null : (String)defaults.get("port"));
            String defaultPath = defaults == null ? null : (String)defaults.get("path");
            Map<String, String> defaultParameters = defaults == null ? null : new HashMap(defaults);
            if (defaultParameters != null) {
                defaultParameters.remove("protocol");
                defaultParameters.remove("username");
                defaultParameters.remove("password");
                defaultParameters.remove("host");
                defaultParameters.remove("port");
                defaultParameters.remove("path");
            }
			//构造URL
            URL u = URL.valueOf(url);
            boolean changed = false;
            String protocol = u.getProtocol();
            String username = u.getUsername();
            String password = u.getPassword();
            String host = u.getHost();
            int port = u.getPort();
            String path = u.getPath();
            Map<String, String> parameters = new HashMap(u.getParameters());
            if ((protocol == null || protocol.length() == 0) && defaultProtocol != null && defaultProtocol.length() > 0) {
                changed = true;
                protocol = defaultProtocol;
            }

            if ((username == null || username.length() == 0) && defaultUsername != null && defaultUsername.length() > 0) {
                changed = true;
                username = defaultUsername;
            }

            if ((password == null || password.length() == 0) && defaultPassword != null && defaultPassword.length() > 0) {
                changed = true;
                password = defaultPassword;
            }

            if (port <= 0) {
                if (defaultPort > 0) {
                    changed = true;
                    port = defaultPort;
                } else {
                    changed = true;
                    port = 9090;
                }
            }

            if ((path == null || path.length() == 0) && defaultPath != null && defaultPath.length() > 0) {
                changed = true;
                path = defaultPath;
            }

            if (defaultParameters != null && defaultParameters.size() > 0) {
                Iterator i$ = defaultParameters.entrySet().iterator();

                label119:
                while(true) {
                    String key;
                    String defaultValue;
                    String value;
                    do {
                        do {
                            do {
                                if (!i$.hasNext()) {
                                    break label119;
                                }

                                Entry<String, String> entry = (Entry)i$.next();
                                key = (String)entry.getKey();
                                defaultValue = (String)entry.getValue();
                            } while(defaultValue == null);
                        } while(defaultValue.length() <= 0);

                        value = (String)parameters.get(key);
                    } while(value != null && value.length() != 0);

                    changed = true;
                    parameters.put(key, defaultValue);
                }
            }
			//如果URL中有username等有一个未指定 则从默认配置读取缺失的配置
            if (changed) {
                u = new URL(protocol, username, password, host, port, path, parameters);
            }

            return u;
        } else {
            return null;
        }
    }

doExportUrlsFor1Protocol

private void doExportUrlsFor1Protocol(ProtocolConfig protocolConfig, List<URL> registryURLs) {
        String name = protocolConfig.getName();
		//设置dubbo为默认协议
        if (name == null || name.length() == 0) {
            name = "dubbo";
        }
		// 添加 side、版本、时间戳以及进程号等信息到 map 中
        Map<String, String> map = new HashMap();
        map.put("side", "provider");
        map.put("dubbo", Version.getVersion());
        map.put("timestamp", String.valueOf(System.currentTimeMillis()));
        if (ConfigUtils.getPid() > 0) {
            map.put("pid", String.valueOf(ConfigUtils.getPid()));
        }
		// 通过反射将对象的字段信息添加到 map 中
        appendParameters(map, this.application);
        appendParameters(map, this.module);
        appendParameters(map, this.provider, "default");
        appendParameters(map, protocolConfig);
        appendParameters(map, this);
		//这段代码用于检测 <dubbo:method> 标签中的配置信息,并将相关配置添加到 map 中。
        if (this.methods != null && this.methods.size() > 0) {
            Iterator i$ = this.methods.iterator();

            label188:
            while(true) {
                MethodConfig method;
                List arguments;
                do {
                    do {
                        if (!i$.hasNext()) {
                            break label188;
                        }

                        method = (MethodConfig)i$.next();
                        appendParameters(map, method, method.getName());
                        String retryKey = method.getName() + ".retry";
                        if (map.containsKey(retryKey)) {
                            String retryValue = (String)map.remove(retryKey);
                            if ("false".equals(retryValue)) {
                                map.put(method.getName() + ".retries", "0");
                            }
                        }

                        arguments = method.getArguments();
                    } while(arguments == null);
                } while(arguments.size() <= 0);

                Iterator i$ = arguments.iterator();

                while(true) {
                    ArgumentConfig argument;
                    Method[] methods;
                    do {
                        do {
                            while(true) {
                                if (!i$.hasNext()) {
                                    continue label188;
                                }

                                argument = (ArgumentConfig)i$.next();
                                if (argument.getType() != null && argument.getType().length() > 0) {
                                    methods = this.interfaceClass.getMethods();
                                    break;
                                }

                                if (argument.getIndex() == -1) {
                                    throw new IllegalArgumentException("argument config must set index or type attribute.eg: <dubbo:argument index='0' .../> or <dubbo:argument type=xxx .../>");
                                }

                                appendParameters(map, argument, method.getName() + "." + argument.getIndex());
                            }
                        } while(methods == null);
                    } while(methods.length <= 0);

                    for(int i = 0; i < methods.length; ++i) {
                        String methodName = methods[i].getName();
                        if (methodName.equals(method.getName())) {
                            Class<?>[] argtypes = methods[i].getParameterTypes();
                            if (argument.getIndex() != -1) {
                                if (!argtypes[argument.getIndex()].getName().equals(argument.getType())) {
                                    throw new IllegalArgumentException("argument config error : the index attribute and type attribute not match :index :" + argument.getIndex() + ", type:" + argument.getType());
                                }

                                appendParameters(map, argument, method.getName() + "." + argument.getIndex());
                            } else {
                                for(int j = 0; j < argtypes.length; ++j) {
                                    Class<?> argclazz = argtypes[j];
                                    if (argclazz.getName().equals(argument.getType())) {
                                        appendParameters(map, argument, method.getName() + "." + j);
                                        if (argument.getIndex() != -1 && argument.getIndex() != j) {
                                            throw new IllegalArgumentException("argument config error : the index attribute and type attribute not match :index :" + argument.getIndex() + ", type:" + argument.getType());
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
		
        String contextPath;
        if (ProtocolUtils.isGeneric(this.generic)) {
            map.put("generic", this.generic);
            map.put("methods", "*");
        } else {
            contextPath = Version.getVersion(this.interfaceClass, this.version);
            if (contextPath != null && contextPath.length() > 0) {
                map.put("revision", contextPath);
            }
			// 为接口生成包裹类 Wrapper,Wrapper 中包含了接口的详细信息,比如接口方法名数组,字段信息等
            String[] methods = Wrapper.getWrapper(this.interfaceClass).getMethodNames();
            if (methods.length == 0) {
                logger.warn("NO method found in service interface " + this.interfaceClass.getName());
                map.put("methods", "*");
            } else {
			// 将逗号作为分隔符连接方法名,并将连接后的字符串放入 map 中
                map.put("methods", StringUtils.join(new HashSet(Arrays.asList(methods)), ","));
            }
        }
		// 添加 token 到 map 中
        if (!ConfigUtils.isEmpty(this.token)) {
            if (ConfigUtils.isDefault(this.token)) {
                map.put("token", UUID.randomUUID().toString());
            } else {
                map.put("token", this.token);
            }
        }

        if ("injvm".equals(protocolConfig.getName())) {
            protocolConfig.setRegister(false);
            map.put("notify", "false");
        }

        contextPath = protocolConfig.getContextpath();
        if ((contextPath == null || contextPath.length() == 0) && this.provider != null) {
            contextPath = this.provider.getContextpath();
        }

        String host = this.findConfigedHosts(protocolConfig, registryURLs, map);
        Integer port = this.findConfigedPorts(protocolConfig, name, map);
		//上面的代码首先是将一些信息,比如版本、时间戳、方法名以及各种配置对象的字段信息放入到 map 中,map 中的内容将作为 URL 的查询字符串。		构建好 map 后,紧接着是获取上下文路径、主机名以及端口号等信息。最后将 map 和主机名等数据传给 URL 构造方法创建 URL 对象。
        URL url = new URL(name, host, port, (contextPath != null && contextPath.length() != 0 ? contextPath + "/" : "") + this.path, map);
		// 加载 ConfiguratorFactory,并生成 Configurator 实例,然后通过实例配置 url
        if (ExtensionLoader.getExtensionLoader(ConfiguratorFactory.class).hasExtension(url.getProtocol())) {
            url = ((ConfiguratorFactory)ExtensionLoader.getExtensionLoader(ConfiguratorFactory.class).getExtension(url.getProtocol())).getConfigurator(url).configure(url);
        }
		
        String scope = url.getParameter("scope");
        if (!"none".toString().equalsIgnoreCase(scope)) {
		    // scope != remote,导出到本地
            if (!"remote".toString().equalsIgnoreCase(scope)) {
                this.exportLocal(url);
            }
			// scope != local,导出到远程
            if (!"local".toString().equalsIgnoreCase(scope)) {
                if (logger.isInfoEnabled()) {
                    logger.info("Export dubbo service " + this.interfaceClass.getName() + " to url " + url);
                }

                if (registryURLs != null && registryURLs.size() > 0) {
                    Iterator i$ = registryURLs.iterator();

                    while(i$.hasNext()) {
                        URL registryURL = (URL)i$.next();
                        url = url.addParameterIfAbsent("dynamic", registryURL.getParameter("dynamic"));
                        URL monitorUrl = this.loadMonitor(registryURL);
                        if (monitorUrl != null) {
                            url = url.addParameterAndEncoded("monitor", monitorUrl.toFullString());
                        }

                        if (logger.isInfoEnabled()) {
                            logger.info("Register dubbo service " + this.interfaceClass.getName() + " url " + url + " to registry " + registryURL);
                        }
						// 为服务提供类(ref)生成 Invoker
                        Invoker<?> invoker = proxyFactory.getInvoker(this.ref, this.interfaceClass, registryURL.addParameterAndEncoded("export", url.toFullString()));
                        DelegateProviderMetaDataInvoker wrapperInvoker = new DelegateProviderMetaDataInvoker(invoker, this);
                        Exporter<?> exporter = protocol.export(wrapperInvoker);
                        this.exporters.add(exporter);
                    }
                } else {
				    // 不存在注册中心,仅导出服务
                    Invoker<?> invoker = proxyFactory.getInvoker(this.ref, this.interfaceClass, url);
                    DelegateProviderMetaDataInvoker wrapperInvoker = new DelegateProviderMetaDataInvoker(invoker, this);
                    Exporter<?> exporter = protocol.export(wrapperInvoker);
                    this.exporters.add(exporter);
                }
            }
        }

        this.urls.add(url);
    }
上面代码根据 url 中的 scope 参数决定服务导出方式,分别如下:
scope = none,不导出服务
scope != remote,导出到本地
scope != local,导出到远程
不管是导出到本地,还是远程。进行服务导出之前,均需要先创建 Invoker

Invoker创建

Invoker 是由 ProxyFactory 创建而来,Dubbo 默认的 ProxyFactory 实现类是 JavassistProxyFactory

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

package com.alibaba.dubbo.rpc.proxy.javassist;

import com.alibaba.dubbo.common.URL;
import com.alibaba.dubbo.common.bytecode.Proxy;
import com.alibaba.dubbo.common.bytecode.Wrapper;
import com.alibaba.dubbo.rpc.Invoker;
import com.alibaba.dubbo.rpc.proxy.AbstractProxyFactory;
import com.alibaba.dubbo.rpc.proxy.AbstractProxyInvoker;
import com.alibaba.dubbo.rpc.proxy.InvokerInvocationHandler;

public class JavassistProxyFactory extends AbstractProxyFactory {
    public JavassistProxyFactory() {
    }

    public <T> T getProxy(Invoker<T> invoker, Class<?>[] interfaces) {
        return Proxy.getProxy(interfaces).newInstance(new InvokerInvocationHandler(invoker));
    }

    public <T> Invoker<T> getInvoker(T proxy, Class<T> type, URL url) {
	// 为目标类创建 Wrapper
        final Wrapper wrapper = Wrapper.getWrapper(proxy.getClass().getName().indexOf(36) < 0 ? proxy.getClass() : type);
		// 创建匿名 Invoker 类对象,并实现 doInvoke 方法。
        return new AbstractProxyInvoker<T>(proxy, type, url) {
            protected Object doInvoke(T proxy, String methodName, Class<?>[] parameterTypes, Object[] arguments) throws Throwable {
                return wrapper.invokeMethod(proxy, methodName, parameterTypes, arguments);
            }
        };
    }
}

JavassistProxyFactory 创建了一个继承自 AbstractProxyInvoker 类的匿名对象,并覆写了抽象方法 doInvoke。覆写后的 doInvoke 逻辑比较简单,仅是将调用请求转发给了 Wrapper 类的 invokeMethod 方法。Wrapper 用于“包裹”目标类,Wrapper 是一个抽象类,仅可通过 getWrapper(Class) 方法创建子类。在创建 Wrapper 子类的过程中,子类代码生成逻辑会对 getWrapper 方法传入的 Class 对象进行解析,拿到诸如类方法,类成员变量等信息。以及生成 invokeMethod 方法代码和其他一些方法代码。代码生成完毕后,通过 Javassist 生成 Class 对象,最后再通过反射创建 Wrapper 实例

Wrapper

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

package com.alibaba.dubbo.common.bytecode;

import com.alibaba.dubbo.common.utils.ClassHelper;
import com.alibaba.dubbo.common.utils.ReflectUtils;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicLong;
import java.util.regex.Matcher;

public abstract class Wrapper {
    private static final Map<Class<?>, Wrapper> WRAPPER_MAP = new ConcurrentHashMap();
    private static final String[] EMPTY_STRING_ARRAY = new String[0];
    private static final String[] OBJECT_METHODS = new String[]{"getClass", "hashCode", "toString", "equals"};
	//Object对象的Wrapper实现
    private static final Wrapper OBJECT_WRAPPER = new Wrapper() {
        public String[] getMethodNames() {
            return Wrapper.OBJECT_METHODS;
        }

        public String[] getDeclaredMethodNames() {
            return Wrapper.OBJECT_METHODS;
        }

        public String[] getPropertyNames() {
            return Wrapper.EMPTY_STRING_ARRAY;
        }

        public Class<?> getPropertyType(String pn) {
            return null;
        }

        public Object getPropertyValue(Object instance, String pn) throws NoSuchPropertyException {
            throw new NoSuchPropertyException("Property [" + pn + "] not found.");
        }

        public void setPropertyValue(Object instance, String pn, Object pv) throws NoSuchPropertyException {
            throw new NoSuchPropertyException("Property [" + pn + "] not found.");
        }

        public boolean hasProperty(String name) {
            return false;
        }

        public Object invokeMethod(Object instance, String mn, Class<?>[] types, Object[] args) throws NoSuchMethodException {
            if ("getClass".equals(mn)) {
                return instance.getClass();
            } else if ("hashCode".equals(mn)) {
                return instance.hashCode();
            } else if ("toString".equals(mn)) {
                return instance.toString();
            } else if ("equals".equals(mn)) {
                if (args.length == 1) {
                    return instance.equals(args[0]);
                } else {
                    throw new IllegalArgumentException("Invoke method [" + mn + "] argument number error.");
                }
            } else {
                throw new NoSuchMethodException("Method [" + mn + "] not found.");
            }
        }
    };
    private static AtomicLong WRAPPER_CLASS_COUNTER = new AtomicLong(0L);

    public Wrapper() {
    }

    public static Wrapper getWrapper(Class<?> c) {
        while(ClassGenerator.isDynamicClass(c)) {
            c = c.getSuperclass();
        }
		//如果是object类型 返回Object的Wrapper
        if (c == Object.class) {
            return OBJECT_WRAPPER;
        } else {
			//从缓存取,没有的话创建Wrapper,并放入缓存
            Wrapper ret = (Wrapper)WRAPPER_MAP.get(c);
            if (ret == null) {
                ret = makeWrapper(c);
                WRAPPER_MAP.put(c, ret);
            }

            return ret;
        }
    }

    private static Wrapper makeWrapper(Class<?> c) {
		//如果是primitive类型 抛异常
        if (c.isPrimitive()) {
            throw new IllegalArgumentException("Can not create wrapper for primitive type: " + c);
        } else {
            String name = c.getName();
            ClassLoader cl = ClassHelper.getClassLoader(c);
			// c1 用于存储 setPropertyValue 方法代码
            StringBuilder c1 = new StringBuilder("public void setPropertyValue(Object o, String n, Object v){ ");
			// c2 用于存储 getPropertyValue 方法代码
            StringBuilder c2 = new StringBuilder("public Object getPropertyValue(Object o, String n){ ");
			// c3 用于存储 invokeMethod 方法代码
            StringBuilder c3 = new StringBuilder("public Object invokeMethod(Object o, String n, Class[] p, Object[] v) throws " + InvocationTargetException.class.getName() + "{ ");
			// 生成类型转换代码及异常捕捉代码,比如:
    //   DemoService w; try { w = ((DemoServcie) $1); }}catch(Throwable e){ throw new IllegalArgumentException(e); }
            c1.append(name).append(" w; try{ w = ((").append(name).append(")$1); }catch(Throwable e){ throw new IllegalArgumentException(e); }");
            c2.append(name).append(" w; try{ w = ((").append(name).append(")$1); }catch(Throwable e){ throw new IllegalArgumentException(e); }");
            c3.append(name).append(" w; try{ w = ((").append(name).append(")$1); }catch(Throwable e){ throw new IllegalArgumentException(e); }");
			 // pts 用于存储成员变量名和类型
            Map<String, Class<?>> pts = new HashMap();
			// ms 用于存储方法描述信息(可理解为方法签名)及 Method 实例
            Map<String, Method> ms = new LinkedHashMap();
			// mns 为方法名列表
            List<String> mns = new ArrayList();
			 // dmns 用于存储“定义在当前类中的方法”的名称
            List<String> dmns = new ArrayList();
            Field[] arr$ = c.getFields();
            int len$ = arr$.length;

            for(int i$ = 0; i$ < len$; ++i$) {
                Field f = arr$[i$];
                String fn = f.getName();
                Class<?> ft = f.getType();
				// 生成条件判断及赋值语句,比如:
        		// if( $2.equals("name") ) { w.name = (java.lang.String) $3; return;}
        		// if( $2.equals("age") ) { w.age = ((Number) $3).intValue(); return;}
                if (!Modifier.isStatic(f.getModifiers()) && !Modifier.isTransient(f.getModifiers())) {
                    c1.append(" if( $2.equals(\"").append(fn).append("\") ){ w.").append(fn).append("=").append(arg(ft, "$3")).append("; return; }");
					 // 生成条件判断及返回语句,比如:
       				 // if( $2.equals("name") ) { return ($w)w.name; }
                    c2.append(" if( $2.equals(\"").append(fn).append("\") ){ return ($w)w.").append(fn).append("; }");
                    pts.put(fn, ft);
                }
            }

            Method[] methods = c.getMethods();
			// 检测 c 中是否包含在当前类中声明的方法
            boolean hasMethod = hasMethods(methods);
            if (hasMethod) {
                c3.append(" try{");
            }

            Method[] arr$ = methods;
            int len$ = methods.length;

            int ix;
            for(int i$ = 0; i$ < len$; ++i$) {
                Method m = arr$[i$];
                if (m.getDeclaringClass() != Object.class) {
                    String mn = m.getName();
                    c3.append(" if( \"").append(mn).append("\".equals( $2 ) ");
                    ix = m.getParameterTypes().length;
					 // 生成“运行时传入的参数数量与方法参数列表长度”判断语句,比如:
        			// && $3.length == 2
                    c3.append(" && ").append(" $3.length == ").append(ix);
                    boolean override = false;
                    Method[] arr$ = methods;
                    int len$ = methods.length;

                    for(int i$ = 0; i$ < len$; ++i$) {
                        Method m2 = arr$[i$];
						// 检测方法是否存在重载情况,条件为:方法对象不同 && 方法名相同
                        if (m != m2 && m.getName().equals(m2.getName())) {
                            override = true;
                            break;
                        }
                    }

                    if (override && ix > 0) {
                        for(int l = 0; l < ix; ++l) {
                            c3.append(" && ").append(" $3[").append(l).append("].getName().equals(\"").append(m.getParameterTypes()[l].getName()).append("\")");
                        }
                    }

                    c3.append(" ) { ");
                    if (m.getReturnType() == Void.TYPE) {
                        c3.append(" w.").append(mn).append('(').append(args(m.getParameterTypes(), "$4")).append(");").append(" return null;");
                    } else {
                        c3.append(" return ($w)w.").append(mn).append('(').append(args(m.getParameterTypes(), "$4")).append(");");
                    }

                    c3.append(" }");
                    mns.add(mn);
                    if (m.getDeclaringClass() == c) {
                        dmns.add(mn);
                    }

                    ms.put(ReflectUtils.getDesc(m), m);
                }
            }

            if (hasMethod) {
                c3.append(" } catch(Throwable e) { ");
                c3.append("     throw new java.lang.reflect.InvocationTargetException(e); ");
                c3.append(" }");
            }

            c3.append(" throw new " + NoSuchMethodException.class.getName() + "(\"Not found method \\\"\"+$2+\"\\\" in class " + c.getName() + ".\"); }");
            Iterator i$ = ms.entrySet().iterator();

            while(i$.hasNext()) {
                Entry<String, Method> entry = (Entry)i$.next();
                String md = (String)entry.getKey();
                Method method = (Method)entry.getValue();
                Matcher matcher;
                String pn;
                if ((matcher = ReflectUtils.GETTER_METHOD_DESC_PATTERN.matcher(md)).matches()) {
                    pn = propertyName(matcher.group(1));
                    c2.append(" if( $2.equals(\"").append(pn).append("\") ){ return ($w)w.").append(method.getName()).append("(); }");
                    pts.put(pn, method.getReturnType());
                } else if ((matcher = ReflectUtils.IS_HAS_CAN_METHOD_DESC_PATTERN.matcher(md)).matches()) {
                    pn = propertyName(matcher.group(1));
                    c2.append(" if( $2.equals(\"").append(pn).append("\") ){ return ($w)w.").append(method.getName()).append("(); }");
                    pts.put(pn, method.getReturnType());
                } else if ((matcher = ReflectUtils.SETTER_METHOD_DESC_PATTERN.matcher(md)).matches()) {
                    Class<?> pt = method.getParameterTypes()[0];
                    String pn = propertyName(matcher.group(1));
                    c1.append(" if( $2.equals(\"").append(pn).append("\") ){ w.").append(method.getName()).append("(").append(arg(pt, "$3")).append("); return; }");
                    pts.put(pn, pt);
                }
            }

            c1.append(" throw new " + NoSuchPropertyException.class.getName() + "(\"Not found property \\\"\"+$2+\"\\\" filed or setter method in class " + c.getName() + ".\"); }");
            c2.append(" throw new " + NoSuchPropertyException.class.getName() + "(\"Not found property \\\"\"+$2+\"\\\" filed or setter method in class " + c.getName() + ".\"); }");
            long id = WRAPPER_CLASS_COUNTER.getAndIncrement();
            ClassGenerator cc = ClassGenerator.newInstance(cl);
            cc.setClassName((Modifier.isPublic(c.getModifiers()) ? Wrapper.class.getName() : c.getName() + "$sw") + id);
            cc.setSuperClass(Wrapper.class);
            cc.addDefaultConstructor();
            cc.addField("public static String[] pns;");
            cc.addField("public static " + Map.class.getName() + " pts;");
            cc.addField("public static String[] mns;");
            cc.addField("public static String[] dmns;");
            int i = 0;

            for(ix = ms.size(); i < ix; ++i) {
                cc.addField("public static Class[] mts" + i + ";");
            }

            cc.addMethod("public String[] getPropertyNames(){ return pns; }");
            cc.addMethod("public boolean hasProperty(String n){ return pts.containsKey($1); }");
            cc.addMethod("public Class getPropertyType(String n){ return (Class)pts.get($1); }");
            cc.addMethod("public String[] getMethodNames(){ return mns; }");
            cc.addMethod("public String[] getDeclaredMethodNames(){ return dmns; }");
            cc.addMethod(c1.toString());
            cc.addMethod(c2.toString());
            cc.addMethod(c3.toString());

            try {
                Class<?> wc = cc.toClass();
                wc.getField("pts").set((Object)null, pts);
                wc.getField("pns").set((Object)null, pts.keySet().toArray(new String[0]));
                wc.getField("mns").set((Object)null, mns.toArray(new String[0]));
                wc.getField("dmns").set((Object)null, dmns.toArray(new String[0]));
                ix = 0;
                Iterator i$ = ms.values().iterator();

                while(i$.hasNext()) {
                    Method m = (Method)i$.next();
                    wc.getField("mts" + ix++).set((Object)null, m.getParameterTypes());
                }

                Wrapper var50 = (Wrapper)wc.newInstance();
                return var50;
            } catch (RuntimeException var27) {
                throw var27;
            } catch (Throwable var28) {
                throw new RuntimeException(var28.getMessage(), var28);
            } finally {
                cc.release();
                ms.clear();
                mns.clear();
                dmns.clear();
            }
        }
    }

    private static String arg(Class<?> cl, String name) {
        if (cl.isPrimitive()) {
            if (cl == Boolean.TYPE) {
                return "((Boolean)" + name + ").booleanValue()";
            } else if (cl == Byte.TYPE) {
                return "((Byte)" + name + ").byteValue()";
            } else if (cl == Character.TYPE) {
                return "((Character)" + name + ").charValue()";
            } else if (cl == Double.TYPE) {
                return "((Number)" + name + ").doubleValue()";
            } else if (cl == Float.TYPE) {
                return "((Number)" + name + ").floatValue()";
            } else if (cl == Integer.TYPE) {
                return "((Number)" + name + ").intValue()";
            } else if (cl == Long.TYPE) {
                return "((Number)" + name + ").longValue()";
            } else if (cl == Short.TYPE) {
                return "((Number)" + name + ").shortValue()";
            } else {
                throw new RuntimeException("Unknown primitive type: " + cl.getName());
            }
        } else {
            return "(" + ReflectUtils.getName(cl) + ")" + name;
        }
    }

    private static String args(Class<?>[] cs, String name) {
        int len = cs.length;
        if (len == 0) {
            return "";
        } else {
            StringBuilder sb = new StringBuilder();

            for(int i = 0; i < len; ++i) {
                if (i > 0) {
                    sb.append(',');
                }

                sb.append(arg(cs[i], name + "[" + i + "]"));
            }

            return sb.toString();
        }
    }

    private static String propertyName(String pn) {
        return pn.length() != 1 && !Character.isLowerCase(pn.charAt(1)) ? pn : Character.toLowerCase(pn.charAt(0)) + pn.substring(1);
    }

    private static boolean hasMethods(Method[] methods) {
        if (methods != null && methods.length != 0) {
            Method[] arr$ = methods;
            int len$ = methods.length;

            for(int i$ = 0; i$ < len$; ++i$) {
                Method m = arr$[i$];
                if (m.getDeclaringClass() != Object.class) {
                    return true;
                }
            }

            return false;
        } else {
            return false;
        }
    }

    public abstract String[] getPropertyNames();

    public abstract Class<?> getPropertyType(String var1);

    public abstract boolean hasProperty(String var1);

    public abstract Object getPropertyValue(Object var1, String var2) throws NoSuchPropertyException, IllegalArgumentException;

    public abstract void setPropertyValue(Object var1, String var2, Object var3) throws NoSuchPropertyException, IllegalArgumentException;

    public Object[] getPropertyValues(Object instance, String[] pns) throws NoSuchPropertyException, IllegalArgumentException {
        Object[] ret = new Object[pns.length];

        for(int i = 0; i < ret.length; ++i) {
            ret[i] = this.getPropertyValue(instance, pns[i]);
        }

        return ret;
    }

    public void setPropertyValues(Object instance, String[] pns, Object[] pvs) throws NoSuchPropertyException, IllegalArgumentException {
        if (pns.length != pvs.length) {
            throw new IllegalArgumentException("pns.length != pvs.length");
        } else {
            for(int i = 0; i < pns.length; ++i) {
                this.setPropertyValue(instance, pns[i], pvs[i]);
            }

        }
    }

    public abstract String[] getMethodNames();

    public abstract String[] getDeclaredMethodNames();

    public boolean hasMethod(String name) {
        String[] arr$ = this.getMethodNames();
        int len$ = arr$.length;

        for(int i$ = 0; i$ < len$; ++i$) {
            String mn = arr$[i$];
            if (mn.equals(name)) {
                return true;
            }
        }

        return false;
    }

    public abstract Object invokeMethod(Object var1, String var2, Class<?>[] var3, Object[] var4) throws NoSuchMethodException, InvocationTargetException;
}

通过 ClassGenerator 为刚刚生成的代码构建 Class 类,并通过反射创建对象。ClassGenerator 是 Dubbo 自己封装的,该类的核心是 toClass() 的重载方法 toClass(ClassLoader, ProtectionDomain),该方法通过 javassist 构建 Class

服务远程导出

  • 调用 doLocalExport 导出服务
  • 向注册中心注册服务
  • 向注册中心进行订阅 override 数据
  • 创建并返回 DestroyableExporter
public <T> Exporter<T> export(Invoker<T> originInvoker) throws RpcException {
 // 导出服务
        RegistryProtocol.ExporterChangeableWrapper<T> exporter = this.doLocalExport(originInvoker);
		 // 获取注册中心 URL,以 zookeeper 注册中心为例,得到的示例 URL 如下:
    // zookeeper://127.0.0.1:2181/com.alibaba.dubbo.registry.RegistryService?application=demo-provider&dubbo=2.0.2&export=dubbo%3A%2F%2F172.17.48.52%3A20880%2Fcom.alibaba.dubbo.demo.DemoService%3Fanyhost%3Dtrue%26application%3Ddemo-provider
        URL registryUrl = this.getRegistryUrl(originInvoker);
        Registry registry = this.getRegistry(originInvoker);
        URL registedProviderUrl = this.getRegistedProviderUrl(originInvoker);
        boolean register = registedProviderUrl.getParameter("register", true);
        ProviderConsumerRegTable.registerProvider(originInvoker, registryUrl, registedProviderUrl);
        if (register) {
            this.register(registryUrl, registedProviderUrl);
            ProviderConsumerRegTable.getProviderWrapper(originInvoker).setReg(true);
        }

        URL overrideSubscribeUrl = this.getSubscribedOverrideUrl(registedProviderUrl);
        RegistryProtocol.OverrideListener overrideSubscribeListener = new RegistryProtocol.OverrideListener(overrideSubscribeUrl, originInvoker);
        this.overrideListeners.put(overrideSubscribeUrl, overrideSubscribeListener);
        registry.subscribe(overrideSubscribeUrl, overrideSubscribeListener);
        return new RegistryProtocol.DestroyableExporter(exporter, originInvoker, overrideSubscribeUrl, registedProviderUrl);
    }

如果是dubbo协议,调用DubboProtocal的export()

 public <T> Exporter<T> export(Invoker<T> invoker) throws RpcException {
        URL url = invoker.getUrl();
        String key = serviceKey(url);
		 // 创建 DubboExporter
        DubboExporter<T> exporter = new DubboExporter(invoker, key, this.exporterMap);
        this.exporterMap.put(key, exporter);
        Boolean isStubSupportEvent = url.getParameter("dubbo.stub.event", false);
        Boolean isCallbackservice = url.getParameter("is_callback_service", false);
        if (isStubSupportEvent && !isCallbackservice) {
            String stubServiceMethods = url.getParameter("dubbo.stub.event.methods");
            if (stubServiceMethods != null && stubServiceMethods.length() != 0) {
                this.stubServiceMethodsMap.put(url.getServiceKey(), stubServiceMethods);
            } else if (this.logger.isWarnEnabled()) {
                this.logger.warn(new IllegalStateException("consumer [" + url.getParameter("interface") + "], has set stubproxy support event ,but no stub methods founded."));
            }
        }
		// 启动服务器
        this.openServer(url);
        return exporter;
    }
 private void openServer(URL url) {
 // 获取 host:port,并将其作为服务器实例的 key,用于标识当前的服务器实例
        String key = url.getAddress();
        boolean isServer = url.getParameter("isserver", true);
        if (isServer) {
            ExchangeServer server = (ExchangeServer)this.serverMap.get(key);
            if (server == null) {
			// 创建服务器实例
                this.serverMap.put(key, this.createServer(url));
            } else {
			// 服务器已创建,则根据 url 中的配置重置服务器
                server.reset(url);
            }
        }

    }

          server = Exchangers.bind(url, this.requestHandler);
            } catch (RemotingException var5) {
                throw new RpcException("Fail to start server(url: " + url + ") " + var5.getMessage(), var5);
            }

            str = url.getParameter("client");
            if (str != null && str.length() > 0) {
                Set<String> supportedTypes = ExtensionLoader.getExtensionLoader(Transporter.class).getSupportedExtensions();
                if (!supportedTypes.contains(str)) {
                    throw new RpcException("Unsupported client type: " + str);
                }
            }

            return server;
        }
    }

调用Exchanger的实现类HeaderExchanger

public class HeaderExchanger implements Exchanger {
    public static final String NAME = "header";

    public HeaderExchanger() {
    }

    public ExchangeClient connect(URL url, ExchangeHandler handler) throws RemotingException {
        return new HeaderExchangeClient(Transporters.connect(url, new ChannelHandler[]{new DecodeHandler(new HeaderExchangeHandler(handler))}), true);
    }

    public ExchangeServer bind(URL url, ExchangeHandler handler) throws RemotingException {
        return new HeaderExchangeServer(Transporters.bind(url, new ChannelHandler[]{new DecodeHandler(new HeaderExchangeHandler(handler))}));
    }
}

Transporters.bind()如下

   public static Server bind(URL url, ChannelHandler... handlers) throws RemotingException {
        if (url == null) {
            throw new IllegalArgumentException("url == null");
        } else if (handlers != null && handlers.length != 0) {
            Object handler;
            if (handlers.length == 1) {
                handler = handlers[0];
            } else {
                handler = new ChannelHandlerDispatcher(handlers);
            }

            return getTransporter().bind(url, (ChannelHandler)handler);
        } else {
            throw new IllegalArgumentException("handlers == null");
        }
    }
	//获取自适应的Transporter扩展 默认NettyTransporter
	public static Transporter getTransporter() {
        return (Transporter)ExtensionLoader.getExtensionLoader(Transporter.class).getAdaptiveExtension();
    }
public class NettyTransporter implements Transporter {
    public static final String NAME = "netty";

    public NettyTransporter() {
    }

    public Server bind(URL url, ChannelHandler listener) throws RemotingException {
        return new NettyServer(url, listener);
    }

    public Client connect(URL url, ChannelHandler listener) throws RemotingException {
        return new NettyClient(url, listener);
    }
}

NettyServer继承AbstractServer,在AbstractServer定义了模板方法doOpen()和doClose(),NettyServer的实现如下

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

package com.alibaba.dubbo.remoting.transport.netty;

import com.alibaba.dubbo.common.Constants;
import com.alibaba.dubbo.common.URL;
import com.alibaba.dubbo.common.logger.Logger;
import com.alibaba.dubbo.common.logger.LoggerFactory;
import com.alibaba.dubbo.common.utils.ExecutorUtil;
import com.alibaba.dubbo.common.utils.NamedThreadFactory;
import com.alibaba.dubbo.common.utils.NetUtils;
import com.alibaba.dubbo.remoting.Channel;
import com.alibaba.dubbo.remoting.ChannelHandler;
import com.alibaba.dubbo.remoting.RemotingException;
import com.alibaba.dubbo.remoting.Server;
import com.alibaba.dubbo.remoting.transport.AbstractServer;
import com.alibaba.dubbo.remoting.transport.dispatcher.ChannelHandlers;
import java.net.InetSocketAddress;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import org.jboss.netty.bootstrap.ServerBootstrap;
import org.jboss.netty.channel.ChannelFactory;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.ChannelPipelineFactory;
import org.jboss.netty.channel.Channels;
import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory;

public class NettyServer extends AbstractServer implements Server {
    private static final Logger logger = LoggerFactory.getLogger(NettyServer.class);
    private Map<String, Channel> channels;
    private ServerBootstrap bootstrap;
    private org.jboss.netty.channel.Channel channel;

    public NettyServer(URL url, ChannelHandler handler) throws RemotingException {
        super(url, ChannelHandlers.wrap(handler, ExecutorUtil.setThreadName(url, "DubboServerHandler")));
    }

    protected void doOpen() throws Throwable {
        NettyHelper.setNettyLoggerFactory();
        ExecutorService boss = Executors.newCachedThreadPool(new NamedThreadFactory("NettyServerBoss", true));
        ExecutorService worker = Executors.newCachedThreadPool(new NamedThreadFactory("NettyServerWorker", true));
        ChannelFactory channelFactory = new NioServerSocketChannelFactory(boss, worker, this.getUrl().getPositiveParameter("iothreads", Constants.DEFAULT_IO_THREADS));
        this.bootstrap = new ServerBootstrap(channelFactory);
        final NettyHandler nettyHandler = new NettyHandler(this.getUrl(), this);
        this.channels = nettyHandler.getChannels();
        this.bootstrap.setPipelineFactory(new ChannelPipelineFactory() {
            public ChannelPipeline getPipeline() {
                NettyCodecAdapter adapter = new NettyCodecAdapter(NettyServer.this.getCodec(), NettyServer.this.getUrl(), NettyServer.this);
                ChannelPipeline pipeline = Channels.pipeline();
                pipeline.addLast("decoder", adapter.getDecoder());
                pipeline.addLast("encoder", adapter.getEncoder());
                pipeline.addLast("handler", nettyHandler);
                return pipeline;
            }
        });
        this.channel = this.bootstrap.bind(this.getBindAddress());
    }

    protected void doClose() throws Throwable {
        try {
            if (this.channel != null) {
                this.channel.close();
            }
        } catch (Throwable var8) {
            logger.warn(var8.getMessage(), var8);
        }

        try {
            Collection<Channel> channels = this.getChannels();
            if (channels != null && channels.size() > 0) {
                Iterator i$ = channels.iterator();

                while(i$.hasNext()) {
                    Channel channel = (Channel)i$.next();

                    try {
                        channel.close();
                    } catch (Throwable var7) {
                        logger.warn(var7.getMessage(), var7);
                    }
                }
            }
        } catch (Throwable var9) {
            logger.warn(var9.getMessage(), var9);
        }

        try {
            if (this.bootstrap != null) {
                this.bootstrap.releaseExternalResources();
            }
        } catch (Throwable var6) {
            logger.warn(var6.getMessage(), var6);
        }

        try {
            if (this.channels != null) {
                this.channels.clear();
            }
        } catch (Throwable var5) {
            logger.warn(var5.getMessage(), var5);
        }

    }

    public Collection<Channel> getChannels() {
        Collection<Channel> chs = new HashSet();
        Iterator i$ = this.channels.values().iterator();

        while(i$.hasNext()) {
            Channel channel = (Channel)i$.next();
            if (channel.isConnected()) {
                chs.add(channel);
            } else {
                this.channels.remove(NetUtils.toAddressString(channel.getRemoteAddress()));
            }
        }

        return chs;
    }

    public Channel getChannel(InetSocketAddress remoteAddress) {
        return (Channel)this.channels.get(NetUtils.toAddressString(remoteAddress));
    }

    public boolean isBound() {
        return this.channel.isBound();
    }
}

© 著作权归作者所有

共有 人打赏支持
秦帝国三川郡守
粉丝 17
博文 69
码字总数 66792
作品 0
宁波
CTO(技术副总裁)
私信 提问
Dubbo 源码分析(一)一环境搭建

环境搭建的步骤有哪些 依赖外部的环境 使用的开发工具 源码的拉取 结构大致介绍 1 依赖的外部环境 安装JDK 安装Git 安装maven 这边我们就不介绍怎么安装这些外部环境了,大家自行从安装这些外...

小刀爱编程
2018/10/19
0
0
探秘Dubbo原理与源码及实操

阅读源码的作用 提取设计思路,增强设计能力 理解运行机制,便于快速解决问题以及功能扩展 常见有关dubbo的问题 dubbo的负载均衡是在哪个组件中处理的? dubbo默认的负载均衡算法是什么? 如...

liwei2000
2018/12/12
0
0
动手学dubbo之初体验

一. 概述 以下部分来源于dubbo用户指南. DUBBO是一个分布式服务框架,致力于提供高性能和透明化的RPC远程服务调用方案,是阿里巴巴SOA服务化治理方案的核心框架,每天为2,000+个服务提供3,0...

ginobefun
2017/07/12
0
0
Dubbo原理和源码解析之服务暴露

一、框架设计 在官方《Dubbo 用户指南》架构部分,给出了服务调用的整体架构和流程: 另外,在官方《Dubbo 开发指南》框架设计部分,给出了整体设计: 以及暴露服务时序图: 本文将根据以上几...

明瞐
2018/09/29
0
0
dubbo源码分析-服务导出(二)

创建注册中心 服务注册操作对于 Dubbo 来说不是必需的,通过服务直连的方式就可以绕过注册中心。但通常我们不会这么做,直连方式不利于服务治理,仅推荐在测试服务时使用。对于 Dubbo 来说,...

秦帝国三川郡守
03/06
0
0

没有更多内容

加载失败,请刷新页面

加载更多

SpringBoot引入第三方jar包或本地jar包的处理方式

在开发过程中有时会用到maven仓库里没有的jar包或者本地的jar包,这时没办法通过pom直接引入,那么该怎么解决呢 一般有两种方法 - 第一种是将本地jar包安装在本地maven库 - 第二种是将本地j...

独钓渔
44分钟前
2
0
五、MyBatis缓存

一、MyBatis缓存介绍 缓存的使用可以明显的加快访问数据速度,提升程序处理性能,生活和工作中,使用缓存的地方很多。在开发过程中,从前端-->后端-->数据库等都涉及到缓存。MyBatis作为数据...

yangjianzhou
今天
2
0
最近研究如何加速UI界面开发,有点感觉了

最近在开发JFinal学院的JBolt开发平台,后端没啥说的,做各种极简使用的封装,开发者上手直接使用。 JBolt开发平台包含常用的用户、角色、权限、字典、全局配置、缓存、增删改查完整模块、电...

山东-小木
今天
3
0
《月亮与六便士》的读后感作文3000字

《月亮与六便士》的读后感作文3000字: 看完英国作家威廉.萨默塞特.毛姆所著《月亮与六便士》(李继宏译),第一疑问就是全书即没提到“月亮”,也没提到“六便士”。那这书名又与内容有什么...

原创小博客
昨天
2
0
微信网页授权获取用户信息(ThinkPHP5)+ 微信发送客服消息(一)

以thinkphp5为实例,创建控制器 class Kf extends Controller { /** * [protected description]微信公众号appid * @var [type] */ protected $appid = "xxxxxxxxxxxxxxx"; /** * [protected......

半缘修道半缘君丶
昨天
2
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部