最近想学习点东西,想来想去,打算看看myfaces的源码。都说看源码能学习到不少好东西。
首先从myfaces的启动开始,在web。xml配置文件中,我们回配置一个contextlistener,
< listener > < listener-class > org.apache.myfaces.webapp.StartupServletContextListener </ listener-class > </ listener >
这个listener对于整个myfaces的运行时时至关重要的,因为在这个license中,myfaces将读取系统中的配置文件
不只是WEB-INF下面的配置文件(下面将说道)。配置包括Application,ViewHandler等重要资源。
/**/ /* * Copyright 2004 The Apache Software Foundation. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.myfaces.webapp; import java.util.Iterator; import java.util.List; import javax.faces.FactoryFinder; import javax.faces.context.ExternalContext; import javax.servlet.ServletContext; import javax.servlet.ServletContextEvent; import javax.servlet.ServletContextListener; import org.apache.myfaces.config.FacesConfigValidator; import org.apache.myfaces.config.FacesConfigurator; import org.apache.myfaces.context.servlet.ServletExternalContextImpl; import org.apache.myfaces.shared_impl.util.ClassUtils; import org.apache.myfaces.shared_impl.util.StateUtils; import org.apache.myfaces.shared_impl.util.serial.DefaultSerialFactory; import org.apache.myfaces.shared_impl.util.serial.SerialFactory; import org.apache.myfaces.shared_impl.webapp.webxml.WebXml; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; /** */ /** * * <p>研发代号: <b>tea</b> </p> * * <p>Title: ×××--×××--×××</p> * <p>Description: 系统启动加载</p> * <p>Copyright: Copyright (c) 2006 wangzj</p> * <p>Company: wangzj</p> * * 创建时间 : 2006-10-26-9:00:44 * @author 学习myfaces源码 * @version $Revision: 1.0 $ * */ public class StartupServletContextListener implements ServletContextListener ... { private static final Log log = LogFactory .getLog(StartupServletContextListener. class ); // 猜测是标志位,判断是否faces_init已经进行 static final String FACES_INIT_DONE = StartupServletContextListener. class .getName()+ " .FACES_INIT_DONE " ; /** */ /** * 监听函数 */ public void contextInitialized(ServletContextEvent event) ... { System.out.println( " ##listener 监听启动。。。 " ); initFaces(event.getServletContext()); } /** */ /** * * @param servletContext servlet上下文 */ public static void initFaces(ServletContext servletContext) ... { try ... { // 判断是否facesContent已经init过 Boolean b = (Boolean) servletContext.getAttribute(FACES_INIT_DONE); if (b == null || b.booleanValue() == false ) ... { log.trace( " Initializing MyFaces " ); // Load the configuration , // 初始化ServletExternalContextImpl的上下文,request,response等对象 // 主要是设置request请求头中的charset(如果求求头中没有), // 但是改servlet因为是启动时记载,所以没有request,不做次处理,只是实例化servletContext ExternalContext externalContext = new ServletExternalContextImpl( servletContext, null , null ); // And configure everything new FacesConfigurator(externalContext).configure(); if ( " true " .equals(servletContext .getInitParameter(FacesConfigValidator.VALIDATE_CONTEXT_PARAM))) ... { List list = FacesConfigValidator.validate(externalContext, servletContext.getRealPath( " / " )); Iterator iterator = list.iterator(); while (iterator.hasNext()) log.warn(iterator.next()); } // parse web.xml WebXml.init(externalContext); servletContext.setAttribute(FACES_INIT_DONE, Boolean.TRUE); } else ... { log.info( " MyFaces already initialized " ); } } catch (Exception ex) ... { log.error( " Error initializing ServletContext " , ex); ex.printStackTrace(); } log.info(" ServletContext ' " + servletContext.getRealPath( " / " ) + " ' initialized. " ); if (servletContext.getInitParameter(StateUtils.INIT_SECRET) != null ) StateUtils.initSecret(servletContext); handleSerialFactory(servletContext); } private static void handleSerialFactory(ServletContext servletContext) ... { String serialProvider = servletContext .getInitParameter(StateUtils.SERIAL_FACTORY); SerialFactory serialFactory = null ; if (serialProvider == null ) ... { serialFactory = new DefaultSerialFactory(); } else ... { try ... { serialFactory = (SerialFactory) ClassUtils .newInstance(serialProvider); } catch (ClassCastException e) ... { log.error( " Make sure ' " + serialProvider + " ' implements the correct interface " , e); } catch (Exception e) ... { log.error(e); } finally ... { if (serialFactory == null ) ... { serialFactory = new DefaultSerialFactory(); log.error( " Using default serialization provider " ); } } } log.info(" Serialization provider : " + serialFactory.getClass()); servletContext.setAttribute(StateUtils.SERIAL_FACTORY, serialFactory); } /** */ /** * 监听函数 */ public void contextDestroyed(ServletContextEvent e) ... { FactoryFinder.releaseFactories(); } }
可以发现在启动的时候系统进行了new FacesConfigurator(externalContext).configure();,进行配置,哈哈,这个可是很重要的,
public void configure() throws FacesException ... { // These two classes can be easily replaced by alternative // implementations. // As long as there is no need to switch implementations we need no // factory pattern to create them. // 初始化unmarshaller对象,作为xml操作的重要工具类,使用apache的digest _unmarshaller = new DigesterFacesConfigUnmarshallerImpl(_externalContext); // 初始化对象,主要用来装载系统一些对象集合,如下 // List applicationFactories = new ArrayList(); // List renderKitFactories = new ArrayList(); _dispenser = new DigesterFacesConfigDispenserImpl(); /** */ /** * 该部分负责加载所有可能的xml配置文件中的配置信息到config中 * 包括标准的xml配置,还有其他的jar中的配置等等 */ try ... { // 加载stander_faces_config.xml,同时将解析的结果存入_dispenser feedStandardConfig(); feedMetaInfServicesFactories(); // feedJarFileConfigurations(); feedClassloaderConfigurations(); feedContextSpecifiedConfig(); feedWebAppConfig(); // 加载web-inf下面的faces-cinfig.xml文件 } catch (IOException e) ... { throw new FacesException(e); } catch (SAXException e) ... { throw new FacesException(e); } configureFactories(); configureApplication(); configureRenderKits(); configureRuntimeConfig(); configureLifecycle(); }
看看吧加载了很多配置,myfaces用的时digester进行解析。