Struts2的启动过程源码分析

 

此文重点分析struts启动的时候加载的配置文件信息:

郑重声明:此篇文章完全是自己经过单步调试、及其自己的理解而写的,其中如有错误之处,还请朋友指点。读者在阅读的时候,如果有问题,还建议去自己探究发现、或者与我交流,不能尽信此文。还有部分的信息是参考网上的,在文章最后备注有参考链接。

我们在XML中配置的就是org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter这个类,这个是进入struts构架的入口,也就是它将struts2嵌入嵌入到我们的工作中。

下面是它的初始化函数,当该函数执行完成之后,也就完成了关于struts2的所有的配置文件的加载。

 

public void init(FilterConfig filterConfig) throws ServletException {
		//InitOperations正如所描述的,里面包含了初始化的操作。
        InitOperations init = new InitOperations();
        try {
			//包装FilterConfig的主机配置
            FilterHostConfig config = new FilterHostConfig(filterConfig);
            init.initLogging(config);
			//其实完成各种配置文件的加载就在这个函数中,详情如下面的解析
            Dispatcher dispatcher = init.initDispatcher(config);
            init.initStaticContentLoader(config, dispatcher);

            prepare = new PrepareOperations(filterConfig.getServletContext(), dispatcher);
            execute = new ExecuteOperations(filterConfig.getServletContext(), dispatcher);
			this.excludedPatterns = init.buildExcludedPatternsList(dispatcher);

            postInit(dispatcher, filterConfig);
        } finally {
            init.cleanup();
        }
    }

 

 现在我们一步一步分析initDispatcherconfig)这个函数

 

 

/**
     * Creates and initializes the dispatcher
     */
    public Dispatcher initDispatcher( HostConfig filterConfig ) {
		/*
首先我们了解一个很重要的类:Dispatcher
正如其帮助文档所写的:A utility class the actual dispatcher delegates most of its tasks to. Each instance of the primary dispatcher holds an instance of this dispatcher to be shared for all requests.
这个类的构造方法:
public Dispatcher(ServletContext servletContext, Map<String, String> initParams) {
        this.servletContext = servletContext;
        this.initParams = initParams;
    }
此处就是构造了这样一个派发对象
*/
        Dispatcher dispatcher = createDispatcher(filterConfig);
		
		/*
		下面的这个函数是初始化配置的入口,请直接看下面init函数的解析
*/
        dispatcher.init();
        return dispatcher;
    } 

 

下面的是org.apache.struts2.dispatcher.Dispatcherinit函数    

 /** Load configurations, including both XML and zero-configuration strategies,
     * and update optional settings, including whether to reload configurations and resource files.
     */
    public void init() {
		//配置管理器,当我们加载完配置之后,由此管理器完成对配置的管理
		/*
在com.opensymphony.xwork2.config.ConfigurationManager中有两个列表变量,就是用来存储各种的配置类:
ContainerProvider的介绍:Provides beans and constants/properties for the Container
private List<ContainerProvider> containerProviders = new CopyOnWriteArrayList<ContainerProvider>();
PackageProvider的介绍:Provides configuration packages.  The separate init and loadPackages calls are due to the need to preserve backwards compatibility with the ConfigurationProvider interface
private List<PackageProvider> packageProviders = new CopyOnWriteArrayList<PackageProvider>();
		*/
    	if (configurationManager == null) {
    		configurationManager = createConfigurationManager(BeanSelectionProvider.DEFAULT_BEAN_NAME);
    	}

        try {
			//下面的七步将完成配置文件的加载

			//org/apache/struts2/default.properties文件的加载
//该配置文件由org.apache.struts2.config. DefaultPropertiesProvider加载(重点留意其中的Register函数)
            init_DefaultProperties(); // [1]

			//完成struts-default.xml,struts-plugin.xml,struts.xml的加载
			// com.opensymphony.xwork2.config.providers. XmlConfigurationProvider中的			register函数将完成XML的解析,详细解析方法可参考源代码
            init_TraditionalXmlConfigurations(); // [2]

			//加载自定义的属性文件:struts.properties
            init_LegacyStrutsProperties(); // [3]

			//加载Web.xml中的配置
            init_CustomConfigurationProviders(); // [5]

			//加载Web.xml中的过滤器参数配置
            init_FilterInitParameters() ; // [6]

//将一个BeanSelectionProvider类追加到ConfigurationManager对象内部的
// ConfigurationProvider队列中
// BeanSelectionProvider主要实现加载org/apache/struts2/struts-messages
            init_AliasStandardObjects() ; // [7]
			
//接下来就开始执行配置文件中的init函数和Register函数
//下面的这个函数会转到:
/*
private Container init_PreloadConfiguration() {
		//获取初始化参数,即上面的七步操作结果
        Configuration config = configurationManager.getConfiguration();
		//这个函数中的重点部分也就是这一句了
//下面我们就看看这个函数的内容,由于无法嵌套注释,还是写到下//面吧
        Container container = config.getContainer();

boolean reloadi18n = Boolean.valueOf(container.getInstance(String.class, StrutsConstants.STRUTS_I18N_RELOAD));
        LocalizedTextUtil.setReloadBundles(reloadi18n);

        return container;
    }
*/
            Container container = init_PreloadConfiguration();
            container.inject(this);
            init_CheckConfigurationReloading(container);
            init_CheckWebLogicWorkaround(container);

            if (!dispatcherListeners.isEmpty()) {
                for (DispatcherListener l : dispatcherListeners) {
                    l.dispatcherInitialized(this);
                }
            }
        } catch (Exception ex) {
            if (LOG.isErrorEnabled())
                LOG.error("Dispatcher initialization failed", ex);
            throw new StrutsException(ex);
        }
    } 

此函数位于:com.opensymphony.xwork2.config. ConfigurationManagerpublic synchronized Configuration 中

		getConfiguration(){//此时会去执行else分支
        if (configuration == null) {
            setConfiguration(createConfiguration(defaultFrameworkBeanName));
            try {
                configuration.reloadContainer(getContainerProviders());
            } catch (ConfigurationException e) {
                setConfiguration(null);
                throw new ConfigurationException("Unable to load configuration.", e);
            }
        } else {
			//看看这个函数的内幕:函数比较长,就单只写一个主要的部分吧
			/*
			……
			if (reload) {
            	for (ContainerProvider containerProvider : containerProviders) {
                	try {
                		containerProvider.destroy();
                	}
                	catch(Exception e) {
                      if (LOG.isWarnEnabled()) {
         LOG.warn("error while destroying configuration provider ["+containerProvider+"]",e);
                            }
                	}
                }
				//重点的也就是这个函数了,它会去执行init和register方法
//此处调用的是com.opensymphony.xwork2.config.impl. //DefaultConfiguration中的重写方法
                packageProviders = configuration.reloadContainer(providers);
				过多的代码此处不写了,只看重要部分:
				ContainerProperties props = new ContainerProperties();
     		   ContainerBuilder builder = new ContainerBuilder();
     		   for (final ContainerProvider containerProvider : providers)
     		   {
					//下面两句就是完成初始化和注册操作
       			     containerProvider.init(this);
       		     containerProvider.register(builder, props);
      			}
			……
*/
            conditionalReload();
        }

        return configuration;
    } 

 至此struts的配置都已经加载完成了。

参考链接:

http://blog.csdn.net/ferry_passion/article/details/7110207

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值