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/

 

posted @ 2021-02-09 14:31  可可逗豆  阅读(157)  评论(0)    收藏  举报