本文主要研究一下dubbo的SpringContainer

Container

dubbo-2.7.2/dubbo-container/dubbo-container-api/src/main/java/org/apache/dubbo/container/Container.java

@SPI("spring")public interface Container {    /**     * start method to load the container.     */    void start();    /**     * stop method to unload the container.     */    void stop();}
  • Container接口定义了start、stop方法

SpringContainer

dubbo-2.7.2/dubbo-container/dubbo-container-spring/src/main/java/org/apache/dubbo/container/spring/SpringContainer.java

public class SpringContainer implements Container {    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(SpringContainer.class);    static ClassPathXmlApplicationContext context;    public static ClassPathXmlApplicationContext getContext() {        return context;    }    @Override    public void start() {        String configPath = ConfigUtils.getProperty(SPRING_CONFIG);        if (StringUtils.isEmpty(configPath)) {            configPath = DEFAULT_SPRING_CONFIG;        }        context = new ClassPathXmlApplicationContext(configPath.split("[,\\s]+"), false);        context.refresh();        context.start();    }    @Override    public void stop() {        try {            if (context != null) {                context.stop();                context.close();                context = null;            }        } catch (Throwable e) {            logger.error(e.getMessage(), e);        }    }}
  • SpringContainer实现了Container接口,其start方法会创建ClassPathXmlApplicationContext,然后执行refresh及start方法;其stop方法执行ClassPathXmlApplicationContext的stop及close方法

Main

dubbo-2.7.2/dubbo-container/dubbo-container-api/src/main/java/org/apache/dubbo/container/Main.java

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);    private static final ExtensionLoader<Container> loader = ExtensionLoader.getExtensionLoader(Container.class);    private static final ReentrantLock LOCK = new ReentrantLock();    private static final Condition STOP = LOCK.newCondition();    public static void main(String[] args) {        try {            if (ArrayUtils.isEmpty(args)) {                String config = ConfigUtils.getProperty(CONTAINER_KEY, loader.getDefaultExtensionName());                args = COMMA_SPLIT_PATTERN.split(config);            }            final List<Container> containers = new ArrayList<Container>();            for (int i = 0; i < args.length; i++) {                containers.add(loader.getExtension(args[i]));            }            logger.info("Use container type(" + Arrays.toString(args) + ") to run dubbo serivce.");            if ("true".equals(System.getProperty(SHUTDOWN_HOOK_KEY))) {                Runtime.getRuntime().addShutdownHook(new Thread("dubbo-container-shutdown-hook") {                    @Override                    public void run() {                        for (Container container : containers) {                            try {                                container.stop();                                logger.info("Dubbo " + container.getClass().getSimpleName() + " stopped!");                            } catch (Throwable t) {                                logger.error(t.getMessage(), t);                            }                            try {                                LOCK.lock();                                STOP.signal();                            } finally {                                LOCK.unlock();                            }                        }                    }                });            }            for (Container container : containers) {                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 e) {            logger.error(e.getMessage(), e);            System.exit(1);        }        try {            LOCK.lock();            STOP.await();        } catch (InterruptedException e) {            logger.warn("Dubbo service server stopped, interrupted by other thread!", e);        } finally {            LOCK.unlock();        }    }}
  • Main的main方法首先加载配置的containers,然后挨个执行start方法;如果配置了shutdownHook则注册dubbo-container-shutdown-hook,挨个调用container的stop方法

小结

SpringContainer实现了Container接口,其start方法会创建ClassPathXmlApplicationContext,然后执行refresh及start方法;其stop方法执行ClassPathXmlApplicationContext的stop及close方法

doc

  • SpringContainer