共计 3422 个字符,预计需要花费 9 分钟才能阅读完成。
序
本文主要研究一下 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
正文完