此文重点分析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();
}
}
现在我们一步一步分析initDispatcher(config)这个函数
/**
* 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.Dispatcher的init函数
/** 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