4. CAT-服务端
源码分析流程
入口
web.xml
com.dianping.cat.servlet.CatServlet
这是web应用初始化加载的类,目的初始化应用的ServletContext
CatServlet extends AbstractContainerServlet
在init方法中调用 抽象初始化方法
protected abstract void initComponents(ServletConfig config) throws Exception
实现类 CatServlet 中实现 init 方法
@Override
protected void initComponents(ServletConfig servletConfig) throws ServletException {
try {
ModuleContext ctx = new DefaultModuleContext(getContainer());
ModuleInitializer initializer = ctx.lookup(ModuleInitializer.class);
File clientXmlFile = getConfigFile(servletConfig, "cat-client-xml", "client.xml");
File serverXmlFile = getConfigFile(servletConfig, "cat-server-xml", "server.xml");
ctx.setAttribute("cat-client-config-file", clientXmlFile);
ctx.setAttribute("cat-server-config-file", serverXmlFile);
initializer.execute(ctx);
} catch (Exception e) {
m_exception = e;
System.err.println(e);
throw new ServletException(e);
}
}
AbstractContainerServlet 服务基类
封装HttpServlet的处理,实现容器的初始化
Container 初始化
public abstract class AbstractContainerServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
private PlexusContainer m_container;
private Logger m_logger;
protected PlexusContainer getContainer() {
return m_container;
}
....
@Override
public void init(ServletConfig config) throws ServletException {
super.init(config);
try {
if (m_container == null) {
m_container = ContainerLoader.getDefaultContainer();
}
m_logger = m_container.getLogger();
initComponents(config);
} catch (Exception e) {
if (m_logger != null) {
m_logger.error("Servlet initializing failed. " + e, e);
} else {
System.out.println("Servlet initializing failed. " + e);
e.printStackTrace(System.out);
}
throw new ServletException("Servlet initializing failed. " + e, e);
}
}
m_container = ContainerLoader.getDefaultContainer()
的初始化
public class ContainerLoader {
private static volatile PlexusContainer s_container;
public static void destroy() {
if (s_container != null) {
s_container.dispose();
s_container = null;
}
}
public static PlexusContainer getDefaultContainer() {
return getDefaultContainer(null);
}
public static PlexusContainer getDefaultContainer(String configuration) {
if (s_container == null) {
synchronized (ContainerLoader.class) {
if (s_container == null) {
try {
if (configuration != null) {
InputStream in = ContainerLoader.class.getClassLoader().getResourceAsStream(configuration);
s_container = new MyPlexusContainer(in);
} else {
s_container = new MyPlexusContainer();
}
} catch (Exception e) {
throw new RuntimeException("Unable to create Plexus container!", e);
}
}
}
}
return s_container;
}
通过 MyPlexusContainer
实例化
public class MyPlexusContainer implements PlexusContainer {
private ComponentManager m_manager;
private Map<String, Object> m_context = new HashMap<String, Object>();
public MyPlexusContainer() throws Exception {
this(null);
}
public MyPlexusContainer(InputStream in) throws Exception {
m_manager = new ComponentManager(this, in);
m_context.put("plexus", this);
}
注意变量
-
m_manager
和 容器面板m_context
public class ComponentManager { // component cache
// role => map (role hint => component)
private Map<String, ComponentBox<?>> m_components = new HashMap<String, ComponentBox<?>>();
private PlexusContainer m_container;
private ComponentLifecycle m_lifecycle;
private ComponentModelManager m_modelManager;
private LoggerManager m_loggerManager;
public ComponentManager(PlexusContainer container, InputStream in) throws Exception {
m_container = container;
m_modelManager = new ComponentModelManager();
m_lifecycle = new ComponentLifecycle(this);
if (in != null) {
m_modelManager.loadComponents(in);
}
m_modelManager.loadComponentsFromClasspath();
// keep it at last
m_loggerManager = lookup(new ComponentKey(LoggerManager.class, null));
register(new ComponentKey(PlexusContainer.class, null), container);
register(new ComponentKey(Logger.class, null), m_loggerManager.getLoggerForComponent(""));
}ComponentModelManager
的实例化m_modelManager = new ComponentModelManager()
m_lifecycle = new ComponentLifecycle(this)
m_modelManager.loadComponentsFromClasspath()
public void loadComponentsFromClasspath() throws Exception { List<URL> urls = scanComponents();
for (URL url : urls) {
loadCompoents(url);
}
}通过
loadCompoents(url)
进入如下代码,加载配置文件package org.unidal.lookup.container; public class ComponentModelManager {
private List<PlexusModel> m_models = new ArrayList<PlexusModel>();
// for test purpose
private PlexusModel m_model = new PlexusModel();
......
private void loadCompoents(URL url) throws IOException, SAXException {
// ignore internals components.xml files within official plexus-container-default.jar
if (url.getPath().contains("/plexus-container-default/")) {
return;
}
InputStream in = url.openStream();
String xml = Files.forIO().readFrom(in, "utf-8");
// to be compatible with plexus.xml
if (xml != null && xml.contains("<component-set>")) {
xml = xml.replace("<component-set>", "<plexus>");
xml = xml.replace("</component-set>", "</plexus>");
}
try {
PlexusModel model = DefaultSaxParser.parse(xml);
m_models.add(model);
} catch (SAXException e) {
System.err.println(String.format("Bad plexus resource(%s): ", url) + xml);
throw e;
}
}
public void loadComponents(InputStream in) throws Exception {
if (in != null) {
try {
PlexusModel model = DefaultSaxParser.parse(in);
m_models.add(model);
} finally {
in.close();
}
}
}
public void loadComponentsFromClasspath() throws Exception {
List<URL> urls = scanComponents();
for (URL url : urls) {
loadCompoents(url);
}
}
public void reset() {
m_model.getComponents().clear();
}
// 需要扫描文件
// META-INF/plexus/plexus.xml|components.xml|components-*.xml
List<URL> scanComponents() throws IOException {
final List<URL> components = new ArrayList<URL>();
Scanners.forResource().scan("META-INF/plexus/", new ResourceMatcher() {
@Override
public Direction matches(URL url, String path) {
if (!path.endsWith(".xml")) {
return Direction.DOWN;
}
// ignore configuration from official plexus-container-default.jar
if (path.contains("/plexus-container-default/")) {
return Direction.NEXT;
}
if (path.equals("plexus.xml")) {
components.add(url);
} else if (path.equals("components.xml") || path.startsWith("components-")) {
components.add(url);
}
return Direction.DOWN;
}
});
return components;
}
文章的剩余部分,由于博客园发布不成功,请阅读 https://keke3394.wordpress.com/2021/01/30/cat-yuan-ma-fen-xi-zheng-li/