Play framework源码解析 Part3:Play的初始化与启动
在上一篇中,我们分析了play的2种启动方式,这一篇,我们来看看Play类的初始化过程 Play类 无论是Server还是ServletWrapper方式运行,在他们的入口中都会运行Play.init()来对Play类进行初始化。那在解析初始化之前,我们先来看看Play类是做什么的,它里面有什么重要的方法。 首先要明确的一点是,Play类是整个Play framework框架的管理、配置中心,它存放了大部分框架需要的成员变量,例如id,配置信息,所有加载的class,使用的插件管理器等等。下图就是Play类中的方法列表。 这其中加注释的几个方法是比较重要的,我们下面便来从init开始一点点剖析Play类中的各个方法。 Play的初始化 public static void init(File root, String id) { // Simple things Play.id = id; Play.started = false; Play.applicationPath = root; // 加载所有 play.static 中的记录的类 initStaticStuff(); //猜测play framework的路径 guessFrameworkPath(); // 读取配置文件 readConfiguration(); Play.classes = new ApplicationClasses(); // 初始化日志 Logger.init(); String logLevel = configuration.getProperty("application.log", "INFO"); //only override log-level if Logger was not configured manually if( !Logger.configuredManually) { Logger.setUp(logLevel); } Logger.recordCaller = Boolean.parseBoolean(configuration.getProperty("application.log.recordCaller", "false")); Logger.info("Starting %s", root.getAbsolutePath()); //设置临时文件夹 if (configuration.getProperty("play.tmp", "tmp").equals("none")) { tmpDir = null; Logger.debug("No tmp folder will be used (play.tmp is set to none)"); } else { tmpDir = new File(configuration.getProperty("play.tmp", "tmp")); if (!tmpDir.isAbsolute()) { tmpDir = new File(applicationPath, tmpDir.getPath()); } if (Logger.isTraceEnabled()) { Logger.trace("Using %s as tmp dir", Play.tmpDir); } if (!tmpDir.exists()) { try { if (readOnlyTmp) { throw new Exception("ReadOnly tmp"); } tmpDir.mkdirs(); } catch (Throwable e) { tmpDir = null; Logger.warn("No tmp folder will be used (cannot create the tmp dir)"); } } } // 设置运行模式 try { mode = Mode.valueOf(configuration.getProperty("application.mode", "DEV").toUpperCase()); } catch (IllegalArgumentException e) { Logger.error("Illegal mode '%s', use either prod or dev", configuration.getProperty("application.mode")); fatalServerErrorOccurred(); } if (usePrecompiled || forceProd) { mode = Mode.PROD; } // 获取http使用路径 ctxPath = configuration.getProperty("http.path", ctxPath); // 设置文件路径 VirtualFile appRoot = VirtualFile.open(applicationPath); roots.add(appRoot); javaPath = new CopyOnWriteArrayList<VirtualFile>(); javaPath.add(appRoot.child("app")); javaPath.add(appRoot.child("conf")); // 设置模板路径 if (appRoot.child("app/views").exists()) { templatesPath = new ArrayList<VirtualFile>(2); templatesPath.add(appRoot.child("app/views")); } else { templatesPath = new ArrayList<VirtualFile>(1); } // 设置路由文件 routes = appRoot.child("conf/routes"); // 设置模块路径 modulesRoutes = new HashMap<String, VirtualFile>(16); // 加载模块 loadModules(); // 模板路径中加入框架自带的模板文件 templatesPath.add(VirtualFile.open(new File(frameworkPath, "framework/templates"))); // 初始化classloader classloader = new ApplicationClassloader(); // Fix ctxPath if ("/".equals(Play.ctxPath)) { Play.ctxPath = ""; } // 设置cookie域名 Http.Cookie.defaultDomain = configuration.getProperty("application.defaultCookieDomain", null); if (Http.Cookie.defaultDomain!=null) { Logger.info("Using default cookie domain: " + Http.Cookie.defaultDomain); } // 加载插件 pluginCollection.loadPlugins(); // 如果是prod直接启动 if (mode == Mode.PROD || System.getProperty("precompile") != null) { mode = Mode.PROD; //预编译 if (preCompile() && System.getProperty("precompile") == null) { start(); } else { return; } } else { Logger.warn("You're running Play! in DEV mode"); } pluginCollection.onApplicationReady(); Play.initialized = true; } 如上面的代码所示,初始化过程主要的顺序为: ...