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); } } }
SPI defaultAnnotation = (SPI)this.type.getAnnotation(SPI.class);
@SPI("spring") public interface Container { void start(); void stop(); }
所以默认加载的是SpringContainer