如何把provider的invoker export出去:1)为原始对象加wrapper,生成invoker;2)给invoker加各种filter,启动监听服务;3)注册服务地址

以HelloService为例:

  1. public interface HelloService {
  2. String sayHello();
  3. }
  1. <dubbo:service interface="com.zhang.HelloService" ref="helloService" />

ServiceConfig和<dubbo:service>基本对应上了。

  1. public interface ApplicationListener {
  2. public void onApplicationEvent(ApplicationEvent event);
  3. }
  4.  
  5. public class ServiceBean<T> extends ServiceConfig<T> implements InitializingBean, ApplicationContextAware, ApplicationListener, BeanNameAware {
  6. public void onApplicationEvent(ApplicationEvent event) {
  7. if (ContextRefreshedEvent.class.getName().equals(event.getClass().getName())) {
  8. if (isDelay()) {
  9. if (logger.isInfoEnabled()) {
  10. logger.info("The service ready on spring started. service: " + getInterface());
  11. }
  12. export();
  13. }
  14. }
  15. }
  16. }
  17.  
  18. public class ServiceConfig<T> extends AbstractServiceConfig {
  19. private ProviderConfig provider;
  20. // 是否暴露
  21. protected Boolean export;
  22.  
  23. private String interfaceName;
  24. private Class<?> interfaceClass;
  25. //即<dubbo:service>的ref对象
  26. private T ref;
  27.  
  28. public synchronized void export() {
  29. if (provider != null) {
  30. if (export == null) {
  31. export = provider.getExport();
  32. }
  33. if (delay == null) {
  34. delay = provider.getDelay();
  35. }
  36. }
  37. if (export != null && ! export.booleanValue()) {
  38. return;
  39. }
  40. if (delay != null && delay > 0) {
  41. Thread thread = new Thread(new Runnable() {
  42. public void run() {
  43. try {
  44. Thread.sleep(delay);
  45. } catch (Throwable e) {
  46. }
  47. doExport();
  48. }
  49. });
  50. thread.setDaemon(true);
  51. thread.setName("DelayExportServiceThread");
  52. thread.start();
  53. } else {
  54. //关于export和delay的配置好像不怎么用,基本走else分支
  55. doExport();
  56. }
  57. }
  58.  
  59. protected synchronized void doExport() {
  60. if (unexported) {
  61. throw new IllegalStateException("Already unexported!");
  62. }
  63. if (exported) {
  64. return;
  65. }
  66. if (interfaceName == null || interfaceName.length() == 0) {
  67. throw new IllegalStateException("<dubbo:service interface=\"\" /> interface not allow null!");
  68. }
  69. checkDefault();
  70. if (provider != null) {
  71. if (application == null) {
  72. application = provider.getApplication();
  73. }
  74. if (registries == null) {
  75. registries = provider.getRegistries();
  76. }
  77. if (monitor == null) {
  78. monitor = provider.getMonitor();
  79. }
  80. if (protocols == null) {
  81. protocols = provider.getProtocols();
  82. }
  83. }
  84. if (application != null) {
  85. if (registries == null) {
  86. registries = application.getRegistries();
  87. }
  88. if (monitor == null) {
  89. monitor = application.getMonitor();
  90. }
  91. }
  92. if (ref instanceof GenericService) {
  93. interfaceClass = GenericService.class;
  94. generic = true;
  95. } else {
  96. try {
  97. interfaceClass = Class.forName(interfaceName, true, Thread.currentThread()
  98. .getContextClassLoader());
  99. } catch (ClassNotFoundException e) {
  100. throw new IllegalStateException(e.getMessage(), e);
  101. }
  102. checkInterfaceAndMethods(interfaceClass, methods);
  103. checkRef();
  104. generic = false;
  105. }
  106. if(local !=null){
  107. if(local=="true"){
  108. local=interfaceName+"Local";
  109. }
  110. Class<?> localClass;
  111. try {
  112. localClass = Class.forName(local);
  113. } catch (ClassNotFoundException e) {
  114. throw new IllegalStateException(e.getMessage(), e);
  115. }
  116. if(!interfaceClass.isAssignableFrom(localClass)){
  117. throw new IllegalStateException("The local implemention class " + localClass.getName() + " not implement interface " + interfaceName);
  118. }
  119. }
  120. if(stub !=null){
  121. if(stub=="true"){
  122. stub=interfaceName+"Stub";
  123. }
  124. Class<?> stubClass;
  125. try {
  126. stubClass = Class.forName(stub);
  127. } catch (ClassNotFoundException e) {
  128. throw new IllegalStateException(e.getMessage(), e);
  129. }
  130. if(!interfaceClass.isAssignableFrom(stubClass)){
  131. throw new IllegalStateException("The stub implemention class " + stubClass.getName() + " not implement interface " + interfaceName);
  132. }
  133. }
  134. checkApplication();
  135. checkRegistry();
  136. checkProtocol();
  137. checkStubAndMock(interfaceClass);
  138. if (path == null || path.length() == 0) {
  139. path = interfaceName;
  140. }
  141. doExportUrls();
  142. exported = true;
  143. }
  144. }

一、生成invoker

ServiceConfig.doExportUrlsFor1Protocol 代码片段:

  1. // ref就是原始对象
  2. Invoker<?> invoker = proxyFactory.getInvoker(ref, (Class) interfaceClass,
  3. registryURL.addParameterAndEncoded(Constants.EXPORT_KEY, url.toFullString()));
  4. // protocol是Protocol$Adpative
  5. Exporter<?> exporter = protocol.export(invoker);
  6. exporters.add(exporter);

以javassist为例,默认从JavassistProxyFactory获取invoker,其实是生成wrapper。

  1. // JavassistProxyFactory
  2. public <T> Invoker<T> getInvoker(T proxy, Class<T> type, URL url) {
  3. // TODO Wrapper类不能正确处理带$的类名。这里的 T proxy 是原始对象
  4. final Wrapper wrapper = Wrapper.getWrapper(proxy.getClass().getName().indexOf('$') < 0 ? proxy.getClass() : type);
  5. return new AbstractProxyInvoker<T>(proxy, type, url) {
  6. @Override
  7. protected Object doInvoke(T proxy, String methodName,
  8. Class<?>[] parameterTypes,
  9. Object[] arguments) throws Throwable {
  10. return wrapper.invokeMethod(proxy, methodName, parameterTypes, arguments);
  11. }
  12. };
  13. }

com.alibaba.dubbo.common.bytecode.Wrapper.makeWrapper(Class<?> c) 方法中生成wrapper类,代码格式化后如下:

  1. public class com.alibaba.dubbo.common.bytecode.Wrapper1 extends Wrapper {
  2. public static String[] pns = null;
  3. public static Map pts = null;
  4. public static String[] mns = { "sayHello" };
  5. public static String[] dmns = { "sayHello" };
  6. public static Class[] mts0 = null;
  7.  
  8. public String[] getPropertyNames() {
  9. return pns;
  10. }
  11.  
  12. public boolean hasProperty(String n) {
  13. return pts.containsKey($1);
  14. }
  15.  
  16. public Class getPropertyType(String n) {
  17. return (Class) pts.get($1);
  18. }
  19.  
  20. public String[] getMethodNames() {
  21. return mns;
  22. }
  23.  
  24. public String[] getDeclaredMethodNames() {
  25. return dmns;
  26. }
  27.  
  28. public void setPropertyValue(Object o, String n, Object v) {
  29. com.zhang.HelloServiceImpl w;
  30. try {
  31. w = ((com.zhang.HelloServiceImpl) $1);
  32. } catch (Throwable e) {
  33. throw new IllegalArgumentException(e);
  34. }
  35. throw new com.alibaba.dubbo.common.bytecode.NoSuchPropertyException(
  36. "Not found property \""
  37. + $2
  38. + "\" filed or setter method in class com.zhang.HelloServiceImpl.");
  39. }
  40.  
  41. public Object getPropertyValue(Object o, String n) {
  42. com.zhang.HelloServiceImpl w;
  43. try {
  44. w = ((com.zhang.HelloServiceImpl) $1);
  45. } catch (Throwable e) {
  46. throw new IllegalArgumentException(e);
  47. }
  48. throw new com.alibaba.dubbo.common.bytecode.NoSuchPropertyException(
  49. "Not found property \""
  50. + $2
  51. + "\" filed or setter method in class com.zhang.HelloServiceImpl.");
  52. }
  53.  
  54. public Object invokeMethod(Object o, String n, Class[] p, Object[] v)
  55. throws java.lang.reflect.InvocationTargetException {
  56. com.zhang.HelloServiceImpl w;
  57. try {
  58. w = ((com.zhang.HelloServiceImpl) $1);
  59. } catch (Throwable e) {
  60. throw new IllegalArgumentException(e);
  61. }
  62. try {
  63. if ("sayHello".equals($2) && $3.length == 0) {
  64. return ($w) w.sayHello();
  65. }
  66. } catch (Throwable e) {
  67. throw new java.lang.reflect.InvocationTargetException(e);
  68. }
  69. throw new com.alibaba.dubbo.common.bytecode.NoSuchMethodException(
  70. "Not found method \"" + $2
  71. + "\" in class com.zhang.HelloServiceImpl.");
  72. }
  73. }

二、开始export。贴出Protocol$Adpative的代码,重点关注export方法:

  1. package com.alibaba.dubbo.rpc;
  2. import com.alibaba.dubbo.common.extension.ExtensionLoader;
  3. public class Protocol$Adpative implements com.alibaba.dubbo.rpc.Protocol {
  4. public void destroy() {
  5. throw new UnsupportedOperationException(
  6. "method public abstract void com.alibaba.dubbo.rpc.Protocol.destroy() of interface com.alibaba.dubbo.rpc.Protocol is not adaptive method!");
  7. }
  8.  
  9. public int getDefaultPort() {
  10. throw new UnsupportedOperationException(
  11. "method public abstract int com.alibaba.dubbo.rpc.Protocol.getDefaultPort() of interface com.alibaba.dubbo.rpc.Protocol is not adaptive method!");
  12. }
  13.  
  14. public com.alibaba.dubbo.rpc.Invoker refer(java.lang.Class arg0,
  15. com.alibaba.dubbo.common.URL arg1) throws java.lang.Class {
  16. if (arg1 == null)
  17. throw new IllegalArgumentException("url == null");
  18. com.alibaba.dubbo.common.URL url = arg1;
  19. String extName = (url.getProtocol() == null ? "dubbo" : url
  20. .getProtocol());
  21. if (extName == null)
  22. throw new IllegalStateException(
  23. "Fail to get extension(com.alibaba.dubbo.rpc.Protocol) name from url("
  24. + url.toString() + ") use keys([protocol])");
  25. com.alibaba.dubbo.rpc.Protocol extension = (com.alibaba.dubbo.rpc.Protocol) ExtensionLoader
  26. .getExtensionLoader(com.alibaba.dubbo.rpc.Protocol.class)
  27. .getExtension(extName);
  28. return extension.refer(arg0, arg1);
  29. }
  30.  
  31. public com.alibaba.dubbo.rpc.Exporter export(
  32. com.alibaba.dubbo.rpc.Invoker arg0)
  33. throws com.alibaba.dubbo.rpc.Invoker {
  34. if (arg0 == null)
  35. throw new IllegalArgumentException(
  36. "com.alibaba.dubbo.rpc.Invoker argument == null");
  37. if (arg0.getUrl() == null)
  38. throw new IllegalArgumentException(
  39. "com.alibaba.dubbo.rpc.Invoker argument getUrl() == null");
  40. com.alibaba.dubbo.common.URL url = arg0.getUrl();
  41. // 根据invoker的url,获取扩展名
  42. String extName = (url.getProtocol() == null ? "dubbo" : url
  43. .getProtocol());
  44. if (extName == null)
  45. throw new IllegalStateException(
  46. "Fail to get extension(com.alibaba.dubbo.rpc.Protocol) name from url("
  47. + url.toString() + ") use keys([protocol])");
  48. com.alibaba.dubbo.rpc.Protocol extension = (com.alibaba.dubbo.rpc.Protocol) ExtensionLoader
  49. .getExtensionLoader(com.alibaba.dubbo.rpc.Protocol.class)
  50. .getExtension(extName);
  51. return extension.export(arg0);
  52. }
  53. }
  54.  
  55. package com.alibaba.dubbo.rpc.cluster;
  56. import com.alibaba.dubbo.common.extension.ExtensionLoader;
  57. public class Cluster$Adpative implements com.alibaba.dubbo.rpc.cluster.Cluster {
  58. public com.alibaba.dubbo.rpc.Invoker join(
  59. com.alibaba.dubbo.rpc.cluster.Directory arg0)
  60. throws com.alibaba.dubbo.rpc.cluster.Directory {
  61. if (arg0 == null)
  62. throw new IllegalArgumentException(
  63. "com.alibaba.dubbo.rpc.cluster.Directory argument == null");
  64. if (arg0.getUrl() == null)
  65. throw new IllegalArgumentException(
  66. "com.alibaba.dubbo.rpc.cluster.Directory argument getUrl() == null");
  67. com.alibaba.dubbo.common.URL url = arg0.getUrl();
  68. String extName = url.getParameter("cluster", "failover");
  69. if (extName == null)
  70. throw new IllegalStateException(
  71. "Fail to get extension(com.alibaba.dubbo.rpc.cluster.Cluster) name from url("
  72. + url.toString() + ") use keys([cluster])");
  73. com.alibaba.dubbo.rpc.cluster.Cluster extension = (com.alibaba.dubbo.rpc.cluster.Cluster) ExtensionLoader
  74. .getExtensionLoader(com.alibaba.dubbo.rpc.cluster.Cluster.class)
  75. .getExtension(extName);
  76. // extension是MockClusterWrapper
  77. return extension.join(arg0);
  78. }
  79. }

从调用栈中能看出,Protocol$Adpative.export调用了两次,在Protocol$Adpative的export函数内部,
第一次获取的protocol是 ProtocolListenerWrapper/ProtocolFilterWrapper/RegistryProtocol,
第二次获取的protocol是 ProtocolListenerWrapper/ProtocolFilterWrapper/DubboProtocol。

第一次:ServiceConfig.doExportUrlsFor1Protocol代码片段:

  1. if (registryURLs != null && registryURLs.size() > 0
  2. && url.getParameter("register", true)) {
  3. for (URL registryURL : registryURLs) {
  4. url = url.addParameterIfAbsent("dynamic", registryURL.getParameter("dynamic"));
  5. URL monitorUrl = loadMonitor(registryURL);
  6. if (monitorUrl != null) {
  7. url = url.addParameterAndEncoded(Constants.MONITOR_KEY, monitorUrl.toFullString());
  8. }
  9. if (logger.isInfoEnabled()) {
  10. logger.info("Register dubbo service " + interfaceClass.getName() + " url " + url + " to registry " + registryURL);
  11. }
  12. // 获取invoker
  13. Invoker<?> invoker = proxyFactory.getInvoker(ref, (Class) interfaceClass, registryURL.addParameterAndEncoded(Constants.EXPORT_KEY, url.toFullString()));
  14. // protocol是Protocol$Adpative
  15. // invoker的url:registry://127.0.0.1:2181/xxxxx
  16. Exporter<?> exporter = protocol.export(invoker);
  17. exporters.add(exporter);
  18. }
  19. } else {
  20. Invoker<?> invoker = proxyFactory.getInvoker(ref, (Class) interfaceClass, url);
  21.  
  22. Exporter<?> exporter = protocol.export(invoker);
  23. exporters.add(exporter);
  24. }

第二次 RegistryProtocol:

  1. // RegistryProtocol
  2. private <T> ExporterChangeableWrapper<T> doLocalExport(final Invoker<T> originInvoker){
  3. String key = getCacheKey(originInvoker);
  4. ExporterChangeableWrapper<T> exporter = (ExporterChangeableWrapper<T>) bounds.get(key);
  5. if (exporter == null) {
  6. synchronized (bounds) {
  7. exporter = (ExporterChangeableWrapper<T>) bounds.get(key);
  8. if (exporter == null) {
  9. final Invoker<?> invokerDelegete =
    new InvokerDelegete<T>(originInvoker, getProviderUrl(originInvoker));
  10. //protocol是com.alibaba.dubbo.rpc.Protocol$Adpative
  11. // invoker的url:dubbo://192.168.233.6:20880
  12. exporter = new ExporterChangeableWrapper<T>((Exporter<T>)protocol.export(invokerDelegete), originInvoker);
  13. bounds.put(key, exporter);
  14. }
  15. }
  16. }
  17. return (ExporterChangeableWrapper<T>) exporter;
  18. }

暴露服务主要的步骤可能在这儿了:

  1. // RegistryProtocol
  2. public <T> Exporter<T> export(final Invoker<T> originInvoker) throws RpcException {
  3. //export invoker 开启服务
  4. final ExporterChangeableWrapper<T> exporter = doLocalExport(originInvoker);
  5. //registry provider 注册服务
  6. final Registry registry = getRegistry(originInvoker);
  7. final URL registedProviderUrl = getRegistedProviderUrl(originInvoker);
  8. registry.register(registedProviderUrl);
  9. // 订阅override数据
  10. // FIXME 提供者订阅时,会影响同一JVM即暴露服务,又引用同一服务的的场景,因为subscribed以服务名为缓存的key,导致订阅信息覆盖。
  11. final URL overrideSubscribeUrl = getSubscribedOverrideUrl(registedProviderUrl);
  12. final OverrideListener overrideSubscribeListener = new OverrideListener(overrideSubscribeUrl);
  13. overrideListeners.put(overrideSubscribeUrl, overrideSubscribeListener);
  14. registry.subscribe(overrideSubscribeUrl, overrideSubscribeListener);
  15. //保证每次export都返回一个新的exporter实例
  16. return new Exporter<T>() {
  17. public Invoker<T> getInvoker() {
  18. return exporter.getInvoker();
  19. }
  20. public void unexport() {
  21. try {
  22. exporter.unexport();
  23. } catch (Throwable t) {
  24. logger.warn(t.getMessage(), t);
  25. }
  26. try {
  27. registry.unregister(registedProviderUrl);
  28. } catch (Throwable t) {
  29. logger.warn(t.getMessage(), t);
  30. }
  31. try {
  32. overrideListeners.remove(overrideSubscribeUrl);
  33. registry.unsubscribe(overrideSubscribeUrl, overrideSubscribeListener);
  34. } catch (Throwable t) {
  35. logger.warn(t.getMessage(), t);
  36. }
  37. }
  38. };
  39. }

在DubboProtocol中export,主要是启动服务:

  1. // DubboProtocol
  2. public <T> Exporter<T> export(Invoker<T> invoker) throws RpcException {
  3. URL url = invoker.getUrl();
  4.  
  5. // export service.
  6. String key = serviceKey(url);
  7. //DubboExporter封装了invoker,invoker对象是RegistryProtocol$InvokerDelegete
  8. DubboExporter<T> exporter = new DubboExporter<T>(invoker, key, exporterMap);
  9. //把exporter放入map中
  10. //key: a/com.zhang.HelloService:20880
  11. //value: DubboExporter
  12. exporterMap.put(key, exporter);
  13.  
  14. //export an stub service for dispaching event
  15. Boolean isStubSupportEvent = url.getParameter(Constants.STUB_EVENT_KEY,Constants.DEFAULT_STUB_EVENT);
  16. Boolean isCallbackservice = url.getParameter(Constants.IS_CALLBACK_SERVICE, false);
  17. if (isStubSupportEvent && !isCallbackservice){
  18. String stubServiceMethods = url.getParameter(Constants.STUB_EVENT_METHODS_KEY);
  19. if (stubServiceMethods == null || stubServiceMethods.length() == 0 ){
  20. if (logger.isWarnEnabled()){
  21. logger.warn(new IllegalStateException("consumer [" +url.getParameter(Constants.INTERFACE_KEY) +
  22. "], has set stubproxy support event ,but no stub methods founded."));
  23. }
  24. } else {
  25. stubServiceMethodsMap.put(url.getServiceKey(), stubServiceMethods);
  26. }
  27. }
  28.  
  29. openServer(url);
  30.  
  31. return exporter;
  32. }
  33.  
  34. private void openServer(URL url) {
  35. // find server.
  36. String key = url.getAddress();
  37. //client 也可以暴露一个只有server可以调用的服务。
  38. boolean isServer = url.getParameter(Constants.IS_SERVER_KEY,true);
  39. if (isServer) {
  40. ExchangeServer server = serverMap.get(key);
  41. if (server == null) {
  42. serverMap.put(key, createServer(url));
  43. } else {
  44. //server支持reset,配合override功能使用
  45. server.reset(url);
  46. }
  47. }
  48. }
  49. private ExchangeServer createServer(URL url) {
  50. //默认开启server关闭时发送readonly事件
  51. url = url.addParameterIfAbsent(Constants.CHANNEL_READONLYEVENT_SENT_KEY, Boolean.TRUE.toString());
  52. //默认开启heartbeat
  53. url = url.addParameterIfAbsent(Constants.HEARTBEAT_KEY, String.valueOf(Constants.DEFAULT_HEARTBEAT));
  54. String str = url.getParameter(Constants.SERVER_KEY, Constants.DEFAULT_REMOTING_SERVER);
  55.  
  56. if (str != null && str.length() > 0 && ! ExtensionLoader.getExtensionLoader(Transporter.class).hasExtension(str))
  57. throw new RpcException("Unsupported server type: " + str + ", url: " + url);
  58.  
  59. url = url.addParameter(Constants.CODEC_KEY, Version.isCompatibleVersion() ? COMPATIBLE_CODEC_NAME : DubboCodec.NAME);
  60. ExchangeServer server;
  61. try {
  62. //requestHandler是DubboProtocol的一个内部类(ExchangeHandlerAdapter)
  63. server = Exchangers.bind(url, requestHandler);
  64. } catch (RemotingException e) {
  65. throw new RpcException("Fail to start server(url: " + url + ") " + e.getMessage(), e);
  66. }
  67. str = url.getParameter(Constants.CLIENT_KEY);
  68. if (str != null && str.length() > 0) {
  69. Set<String> supportedTypes = ExtensionLoader.getExtensionLoader(Transporter.class).getSupportedExtensions();
  70. if (!supportedTypes.contains(str)) {
  71. throw new RpcException("Unsupported client type: " + str);
  72. }
  73. }
  74. return server;
  75. }

绑定requestHandler

  1. // Exchangers
  2. public static ExchangeServer bind(URL url, ExchangeHandler handler) throws RemotingException {
  3. if (url == null) {
  4. throw new IllegalArgumentException("url == null");
  5. }
  6. if (handler == null) {
  7. throw new IllegalArgumentException("handler == null");
  8. }
  9. url = url.addParameterIfAbsent(Constants.CODEC_KEY, "exchange");
  10. return getExchanger(url).bind(url, handler);
  11. }
  12.  
  13. // HeaderExchanger
  14. public ExchangeServer bind(URL url, ExchangeHandler handler) throws RemotingException {
  15. return new HeaderExchangeServer(Transporters.bind(url, new DecodeHandler(new HeaderExchangeHandler(handler))));
  16. }

dubbo provider如何对invoker进行export的更多相关文章

  1. Nodejs“实现”Dubbo Provider

    背景 目前nodejs应用越来越广泛,但和java的dubbo体系接入困难,所以我们需要实现node端的dubbo provider逻辑.java的dubbo provider是和consumer在一 ...

  2. dubbo.provider和dubbo.consumer配置

    Configure service provider <?xml version="1.0" encoding="UTF-8"?> <bean ...

  3. Apache Dubbo Provider默认反序列漏洞复现(CVE-2020-1948)

    Apache Dubbo Provider默认反序列漏洞(CVE-2020-1948) 0x01 搭建漏洞环境 漏洞介绍 2020年06月23日, 360CERT监测发现Apache Dubbo 官方 ...

  4. 【CVE-2020-1948】Apache Dubbo Provider反序列化漏洞复现

    一.实验简介 实验所属系列: 系统安全 实验对象:本科/专科信息安全专业 相关课程及专业: 计算机网络 实验时数(学分):2 学时 实验类别: 实践实验类 二.实验目的 Apache Dubbo是一款 ...

  5. dubbo源码—service export

    在应用编写好服务并进行之后,dubbo负责将服务export出去,dubbo export服务的时候主要做了以下几件事: 将服务export到本地(根据scope的配置) 创建Invoker(启动本地 ...

  6. Dubbo实践(十三)Export

    Spring在启动Dubbo服务端应用时,会实例化ServiceBean<T>并设置配置属性,然后调用export方法: @SuppressWarnings({"unchecke ...

  7. dubbo源码分析14——DubboProtocol的export方法分析

    走到了这一步也挺不容易的,把之前的暴露入口代码再列出来回顾一下: //配置为none不暴露 if (! Constants.SCOPE_NONE.toString().equalsIgnoreCase ...

  8. 【dubbo】dubbo项目基本结构及provider构建

    dubbo项目基本结构如下,分别部署于不同服务器: 1.provider(接口API 实现) 2.consumer(web) 3.zookeeper 4.DB provider构建 1.api构建 i ...

  9. Dubbo源码学习--服务发布(ProxyFactory、Invoker)

    上文分析了Dubbo服务发布的整体流程,但服务代理生成的具体细节介绍得还不是很详细.下面将会接着上文继续分析.上文介绍了服务代理生成的切入点,如下: Invoker<?> invoker ...

随机推荐

  1. Java的各种加密算法

    Java的各种加密算法 JAVA中为我们提供了丰富的加密技术,可以基本的分为单向加密和非对称加密 1.单向加密算法 单向加密算法主要用来验证数据传输的过程中,是否被篡改过. BASE64 严格地说,属 ...

  2. spring mvc @ModelAttribute 每次执行requestmapping前自动执行

    在不少应用场景中,我们希望在每次执行requestmapping前自动执行一些操作,比如把某些数据(比如数据字典.系统配置.标准错误号,这在企业应用系统中极为常见)塞到model中供view访问,因为 ...

  3. logistic回归和softmax回归

    logistic回归 在 logistic 回归中,我们的训练集由  个已标记的样本构成:.由于 logistic 回归是针对二分类问题的,因此类标记 . 假设函数(hypothesis functi ...

  4. 关于定时器、波特率、TH和TL值的计算

    假设晶振位6MHZ,定时10ms 单片机系统晶振频率为6mhz,系统时钟频率 (也是计时脉冲频率)为500KHZ,一个脉冲周期2us ,10ms是5000个脉冲,因此TMOD=0X01;TH0=(65 ...

  5. WinForm画网格并填充颜色

    因为研究CodeCombat上的最后一题,自己尝试分解题目,然后想到需要画网格,还有最优化的方法 源代码如下 using System; using System.Collections.Generi ...

  6. 【第八章】 springboot + mybatis + 多数据源

    在实际开发中,我们一个项目可能会用到多个数据库,通常一个数据库对应一个数据源. 代码结构: 简要原理: 1)DatabaseType列出所有的数据源的key---key 2)DatabaseConte ...

  7. BZOJ5293: [Bjoi2018]求和 树上差分

    Description master 对树上的求和非常感兴趣.他生成了一棵有根树,并且希望多次询问这棵树上一段路径上所有节点深度的k  次方和,而且每次的k 可能是不同的.此处节点深度的定义是这个节点 ...

  8. require的shim解释

    通过require加载的模块一般都需要符合AMD规范即使用define来申明模块,但是部分时候需要加载非AMD规范的js,这时候就需要用到另一个功能:shim,shim解释起来也比较难理解,shim直 ...

  9. [Java] - MySQL数据库的时间设置问题.

    之前有朋友做的项目时间格式设置为String,我感觉很不好,随后自己试了试. 首先在设置数据库类型时,选择的是timestamp, 而Java的实体中设置时间的属性类型为Date, (java.uti ...

  10. java自学入门心得体会 从环境配置开始

    java —— 一种可以撰写跨平台应用软件的面向对象的程序设计语言. 很多教程里都要概述java语言的诞生发明.其实像图灵的”图灵机“和”图灵测试“一样,当初的java并不是这样. 是用来操控一些电冰 ...