dubbo-源码阅读之容器启动
dubbo Main
例子
public class Start { public static void main(String[] args) throws Exception { com.alibaba.dubbo.container.Main.main(args); } }
源码
public class Main { //系统变量 public static final String CONTAINER_KEY = "dubbo.container"; public static final String SHUTDOWN_HOOK_KEY = "dubbo.shutdown.hook"; private static final Logger logger = LoggerFactory.getLogger(Main.class); //SPI的container Loader容器 private static final ExtensionLoader<Container> loader = ExtensionLoader.getExtensionLoader(Container.class); private static final ReentrantLock LOCK = new ReentrantLock(); private static final Condition STOP; public Main() { } public static void main(String[] args) { try { //如果没有启动参数 if (args == null || args.length == 0) { //获得系统变量 如jvm参数配置的-Ddubbo.container=spiKey 如果没有则使用loader.getDefaultExtensionName()的 String config = ConfigUtils.getProperty("dubbo.container", loader.getDefaultExtensionName()); //分割 args = Constants.COMMA_SPLIT_PATTERN.split(config); } //容器 可以多容器启动 final List<Container> containers = new ArrayList(); for(int i = 0; i < args.length; ++i) { //spi获取对应容器实现 containers.add(loader.getExtension(args[i])); } logger.info("Use container type(" + Arrays.toString(args) + ") to run dubbo serivce."); /** * 埋点 jvm关闭时 关闭容器 *kill pid会优雅关闭 则有新的请求拒绝 等没有进行中的请求 才关闭 *kill -9并不会优雅关闭 */ if ("true".equals(System.getProperty("dubbo.shutdown.hook"))) { Runtime.getRuntime().addShutdownHook(new Thread() { public void run() { Iterator i$ = containers.iterator(); //遍历容器执行stop while(i$.hasNext()) { Container container = (Container)i$.next(); try { container.stop(); Main.logger.info("Dubbo " + container.getClass().getSimpleName() + " stopped!"); } catch (Throwable var8) { Main.logger.error(var8.getMessage(), var8); } try { Main.LOCK.lock(); //类型Object的notify Main.STOP.signal(); } finally { Main.LOCK.unlock(); } } } }); } Iterator i$ = containers.iterator(); //循环启动容器 while(i$.hasNext()) { Container container = (Container)i$.next(); container.start(); logger.info("Dubbo " + container.getClass().getSimpleName() + " started!"); } System.out.println((new SimpleDateFormat("[yyyy-MM-dd HH:mm:ss]")).format(new Date()) + " Dubbo service server started!"); } catch (RuntimeException var10) { var10.printStackTrace(); logger.error(var10.getMessage(), var10); System.exit(1); } try { LOCK.lock(); /** * 阻塞 防止应用程序结束 * 类似object的wait() */ STOP.await(); } catch (InterruptedException var8) { logger.warn("Dubbo service server stopped, interrupted by other thread!", var8); } finally { LOCK.unlock(); } } static { //condition可参考资料https://blog.csdn.net/andyzhaojianhui/article/details/79361454 STOP = LOCK.newCondition(); } }
loader.getDefaultExtensionName()
public class ExtensionLoader<T> { private final Holder<Map<String, Class<?>>> cachedClasses = new Holder(); public String getDefaultExtensionName() { this.getExtensionClasses(); return this.cachedDefaultName; } private Map<String, Class<?>> getExtensionClasses() { //默认Holder容器是空的 Map<String, Class<?>> classes = (Map)this.cachedClasses.get(); if (classes == null) { Holder var2 = this.cachedClasses; synchronized(this.cachedClasses) { //防止缓存穿透 重复加载 加了一层判断 classes = (Map)this.cachedClasses.get(); if (classes == null) { //真正加载的地方 classes = this.loadExtensionClasses(); this.cachedClasses.set(classes); } } } return classes; } private Map<String, Class<?>> loadExtensionClasses() { /** * 获得Container上的SPI注解 private static final ExtensionLoader<Container> loader = ExtensionLoader.getExtensionLoader(Container.class); * type为Container */ SPI defaultAnnotation = (SPI)this.type.getAnnotation(SPI.class); if (defaultAnnotation != null) { //获取SPI上面的名字 String value = defaultAnnotation.value(); if ((value = value.trim()).length() > 0) { String[] names = NAME_SEPARATOR.split(value); if (names.length > 1) { throw new IllegalStateException("more than 1 default extension name on extension " + this.type.getName() + ": " + Arrays.toString(names)); } if (names.length == 1) { this.cachedDefaultName = names[0]; } } } Map<String, Class<?>> extensionClasses = new HashMap(); //加载这个目录下的spi文件配置 META-INF/dubbo/internal/com.alibaba.dubbo.container.Container this.loadDirectory(extensionClasses, "META-INF/dubbo/internal/"); //加载这个目录下的spi文件配置 META-INF/dubbo/com.alibaba.dubbo.container.Container this.loadDirectory(extensionClasses, "META-INF/dubbo/"); //加载这个目录下的spi文件配置META-INF/dubbo/services/com.alibaba.dubbo.container.Container this.loadDirectory(extensionClasses, "META-INF/services/"); return extensionClasses; } private void loadDirectory(Map<String, Class<?>> extensionClasses, String dir) { //加载这个目录下的spi文件配置 META-INF/dubbo/internal/com.alibaba.dubbo.container.Container String fileName = dir + this.type.getName(); try { ClassLoader classLoader = findClassLoader(); Enumeration urls; if (classLoader != null) { urls = classLoader.getResources(fileName); } else { urls = ClassLoader.getSystemResources(fileName); } if (urls != null) { while(urls.hasMoreElements()) { java.net.URL resourceURL = (java.net.URL)urls.nextElement(); this.loadResource(extensionClasses, classLoader, resourceURL); } } } catch (Throwable var7) { logger.error("Exception when load extension class(interface: " + this.type + ", description file: " + fileName + ").", var7); } } }
SpringContainer
例子
源码
public class SpringContainer implements Container { //可以系统变量指定spring xml配置 public static final String SPRING_CONFIG = "dubbo.spring.config"; //默认的位置 public static final String DEFAULT_SPRING_CONFIG = "classpath*:META-INF/spring/*.xml"; private static final Logger logger = LoggerFactory.getLogger(com.alibaba.dubbo.container.spring.SpringContainer.class); static ClassPathXmlApplicationContext context; public SpringContainer() { } public static ClassPathXmlApplicationContext getContext() { return context; } public void start() { //获取系统变量指定的spring配置文件位置 String configPath = ConfigUtils.getProperty("dubbo.spring.config"); if (configPath == null || configPath.length() == 0) { //没有指定取默认的 configPath = "classpath*:META-INF/spring/*.xml"; } //初始化spring容器 context = new ClassPathXmlApplicationContext(configPath.split("[,\\s]+")); //start开始解析spring相关xml 以及dubbo基于spring2.0 schema解析dubbo相关配置以及初始化 context.start(); } public void stop() { try { if (context != null) { context.stop(); context.close(); context = null; } } catch (Throwable var2) { logger.error(var2.getMessage(), var2); } } }
dubbo-源码阅读之容器启动的更多相关文章
- 【Dubbo源码阅读系列】之远程服务调用(上)
今天打算来讲一讲 Dubbo 服务远程调用.笔者在开始看 Dubbo 远程服务相关源码的时候,看的有点迷糊.后来慢慢明白 Dubbo 远程服务的调用的本质就是动态代理模式的一种实现.本地消费者无须知道 ...
- 【Dubbo源码阅读系列】服务暴露之远程暴露
引言 什么叫 远程暴露 ?试着想象着这么一种场景:假设我们新增了一台服务器 A,专门用于发送短信提示给指定用户.那么问题来了,我们的 Message 服务上线之后,应该如何告知调用方服务器,服务器 A ...
- 【Dubbo源码阅读系列】服务暴露之本地暴露
在上一篇文章中我们介绍 Dubbo 自定义标签解析相关内容,其中我们自定义的 XML 标签 <dubbo:service /> 会被解析为 ServiceBean 对象(传送门:Dubbo ...
- 【Dubbo源码阅读系列】之 Dubbo SPI 机制
最近抽空开始了 Dubbo 源码的阅读之旅,希望可以通过写文章的方式记录和分享自己对 Dubbo 的理解.如果在本文出现一些纰漏或者错误之处,也希望大家不吝指出. Dubbo SPI 介绍 Java ...
- Dubbo源码阅读顺序
转载: https://blog.csdn.net/heroqiang/article/details/85340958 Dubbo源码解析之配置解析篇,主要内容是<dubbo:service/ ...
- Fabric1.4源码解析: 链码容器启动过程
想写点东西记录一下最近看的一些Fabric源码,本文使用的是fabric1.4的版本,所以对于其他版本的fabric,内容可能会有所不同. 本文想针对Fabric中链码容器的启动过程进行源码的解析.这 ...
- spring源码:web容器启动(li)
web项目中可以集成spring的ApplicationContext进行bean的管理,这样使用起来bean更加便捷,能够利用到很多spring的特性.我们比较常用的web容器有jetty,tomc ...
- spring源码:web容器启动
web项目中可以集成spring的ApplicationContext进行bean的管理,这样使用起来bean更加便捷,能够利用到很多spring的特性.我们比较常用的web容器有jetty,tomc ...
- Dubbo源码阅读-服务导出
Dubbo服务导出过程始于Spring容器发布刷新事件,Dubbo在接收到事件后,会立即执行服务导出逻辑.整个逻辑大致可分为三个部分,第一部分是前置工作,主要用于检查参数,组装URL.第二部分是导出服 ...
随机推荐
- centos7下的Firewalld
一.介绍 防火墙守护 firewalld 服务引入了一个信任级别的概念来管理与之相关联的连接与接口.它支持 ipv4 与 ipv6,并支持网桥,采用 firewall-cmd (command) 或 ...
- android中返回数据给上一个活动,可以用来回显数据
(一)who简介:没错,就是startActivityForResult()方法,这个方法用来在活动被销毁的时候返回数据给上一个方法.参数说明: startActivityForResult(inte ...
- H5 移动调试全攻略
H5 移动调试全攻略 随着移动设备的高速发展,H5 开发也成为了 F2E 不可或缺的能力.而移动开发的重中之重就是掌握调试技巧,定 Bug于无形. 一.概要 因为移动端操作系统分为 iOS 和 And ...
- zoj 2112 单点修改的主席树(树状数组套主席树)
题目大意: 区间第k大问题+单点修改 基本思路: 这个题有用整体二分,cdq分治,还有主席树+平衡树的,还有就是主席树+树状数组. 我采用的是b站电子科大大佬的主席树写法,尤其喜欢他的离散化方法,所以 ...
- windows 安装yaml支持和pytest支持等
打开cmd 输入pip install pyyaml #yaml文件支持 输入pip install pytest #pytest框架支持 输入pip install requests ...
- 关键字group by 、 Having的 用法
概述 GROUP BY我们可以先从字面上来理解,GROUP表示分组,BY后面写字段名,就表示根据哪个字段进行分组,如果有用Excel比较多的话,GROUP BY比较类似Excel里面的透视表. GRO ...
- paper 147:Deep Learning -- Face Data Augmentation(一)
1. 在深度学习中,当数据量不够大时候,常常采用下面4中方法: (1)人工增加训练集的大小. 通过平移, 翻转, 加噪声等方法从已有数据中创造出一批"新"的数据.也就是Data ...
- MFC对话框编程详细学习笔记
因最近研究工作要用到MFC,故再次重温了孙鑫老师的MFC对话框编程,因所用的编译软件为VS2008,与视频中孙老师使用的VC++6.0有很大出入,造成很大不便,我通过各方查找,实现了VS2008相对应 ...
- redis安装-1
redis安装 cd /opt/tools/ #包目录 tar -xf redis-.tar.gz cd redis- make#centos7安装 make MALLOC=libc && ...
- ERROR in Error: ***Module is not an NgModule
引入一个打包的模块时报了这个个错: $ rimraf out Done in 16.81s. lerna ERR! build Errored while running script in 'map ...