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-源码阅读之容器启动的更多相关文章

  1. 【Dubbo源码阅读系列】之远程服务调用(上)

    今天打算来讲一讲 Dubbo 服务远程调用.笔者在开始看 Dubbo 远程服务相关源码的时候,看的有点迷糊.后来慢慢明白 Dubbo 远程服务的调用的本质就是动态代理模式的一种实现.本地消费者无须知道 ...

  2. 【Dubbo源码阅读系列】服务暴露之远程暴露

    引言 什么叫 远程暴露 ?试着想象着这么一种场景:假设我们新增了一台服务器 A,专门用于发送短信提示给指定用户.那么问题来了,我们的 Message 服务上线之后,应该如何告知调用方服务器,服务器 A ...

  3. 【Dubbo源码阅读系列】服务暴露之本地暴露

    在上一篇文章中我们介绍 Dubbo 自定义标签解析相关内容,其中我们自定义的 XML 标签 <dubbo:service /> 会被解析为 ServiceBean 对象(传送门:Dubbo ...

  4. 【Dubbo源码阅读系列】之 Dubbo SPI 机制

    最近抽空开始了 Dubbo 源码的阅读之旅,希望可以通过写文章的方式记录和分享自己对 Dubbo 的理解.如果在本文出现一些纰漏或者错误之处,也希望大家不吝指出. Dubbo SPI 介绍 Java ...

  5. Dubbo源码阅读顺序

    转载: https://blog.csdn.net/heroqiang/article/details/85340958 Dubbo源码解析之配置解析篇,主要内容是<dubbo:service/ ...

  6. Fabric1.4源码解析: 链码容器启动过程

    想写点东西记录一下最近看的一些Fabric源码,本文使用的是fabric1.4的版本,所以对于其他版本的fabric,内容可能会有所不同. 本文想针对Fabric中链码容器的启动过程进行源码的解析.这 ...

  7. spring源码:web容器启动(li)

    web项目中可以集成spring的ApplicationContext进行bean的管理,这样使用起来bean更加便捷,能够利用到很多spring的特性.我们比较常用的web容器有jetty,tomc ...

  8. spring源码:web容器启动

    web项目中可以集成spring的ApplicationContext进行bean的管理,这样使用起来bean更加便捷,能够利用到很多spring的特性.我们比较常用的web容器有jetty,tomc ...

  9. Dubbo源码阅读-服务导出

    Dubbo服务导出过程始于Spring容器发布刷新事件,Dubbo在接收到事件后,会立即执行服务导出逻辑.整个逻辑大致可分为三个部分,第一部分是前置工作,主要用于检查参数,组装URL.第二部分是导出服 ...

随机推荐

  1. Codeforces 362E 费用流

    题意及思路:https://blog.csdn.net/mengxiang000000/article/details/52472696 代码: #define Hello the_cruel_wor ...

  2. 十、设计模式之代理(Proxy)模式

    什么是代理模式 代理模式是对象的结构模式,为其他对象提供一种对象以控制对这个对象的访问. 代理模式的结构图如下:(源自大话设计模式)   Subject:定义了RealSubject和Proxy的公共 ...

  3. Linux下的上传和下载yum install -y lrzsz

    先使用命令 yum install -y lrzsz rz 上传    或者直接拖动 sz 要下的文件 回车

  4. oracle11g rename user导致物化视图失效的处理

    在上一篇文章中,已经点到了数据库改名时,引起该schema下物化视图会失效的问题.从表面上看,该物化视图是删也删不掉,那当然就无法重建了.以下是实验过程: Oracle Database 11g En ...

  5. OpenCV常用基本处理函数(1)读写

    图像的基本操作 cv.imread()      读取图片 cv.imshow()     显示图片 cv2.imwrite()    保存图像 使用摄像头捕获实时图像 OpenCV 为这中应用提供了 ...

  6. leetcode-第14周双周赛-1274-矩形内船只的数目

    题目描述: 自己的提交: # """ # This is Sea's API interface. # You should not implement it, or s ...

  7. Linux进程管理之ps的使用

    主题Linux进程管理之ps工具的使用 一ps工具的介绍 ps: process state  进程状态ps - report a snapshot of the current processesL ...

  8. vue 之组件

    组件 '''1.根组件:new Vue()创建的组件,一般不明确自身的模板,模板就采用挂载点2.局部组件: local_component = {}2.全局组件: Vue.component({})' ...

  9. Delphi RegisterHotKey 设置系统热键

    Symbolic constant name Value (hexadecimal) Keyboard (or mouse) equivalent VK_LBUTTON 01 Left mouse b ...

  10. JavaScript实现注册时检查邮箱,名称,密码等是否符合规则

    大概实现了,用户名是否存在,邮箱是否已注册,密码是否符合复杂度. //对用户名校验是否存在function checkname(){ //alert("checkname"); v ...