接下来第三步:init_LegacyStrutsProperties()
调用的是调用的是LegacyPropertiesConfigurationProvider
通过比较前面DefaultPropertiesProvider与调用的是LegacyPropertiesConfigurationProvider.
发现DefaultPropertiesProvider继承自后者,但重写了register()方法,主要是生成PropertiesSetting的不同,前者是根据org/apache/struts2/default.properties
后者是根据struts.properties
我们展开register()中的Settings.getInstance(),最后是调用getDefaultInstance()
- private static Settings getDefaultInstance() {
- if (defaultImpl == null) {
- // Create bootstrap implementation
- //不带参数的DefaultSettings(),区别与DefaultPropertiesProvider中直接带default.properties参数
- //不带参数就是默认为struts.propertes,并且加载struts.custom.properties所定义的properties文件
- defaultImpl = new DefaultSettings();
- // Create default implementation
- try {
- //STRUTS_CONFIGURATION为:struts.configuration
- //在struts.proterties中查找struts.configuration的值,这个值必须是org.apache.struts2.config.Configuration接口的实现类
- //所以我有个困惑就是在下面的转换当中怎么将Configuration转换成Setting类型的...
- //这一点先放下了,有时间再研究
- String className = get(StrutsConstants.STRUTS_CONFIGURATION);
- if (!className.equals(defaultImpl.getClass().getName())) {
- try {
- // singleton instances shouldn't be built accessing request or session-specific context data
- defaultImpl = (Settings) ObjectFactory.getObjectFactory().buildBean(Thread.currentThread().getContextClassLoader().loadClass(className), null);
- } catch (Exception e) {
- LOG.error("Settings: Could not instantiate the struts.configuration object, substituting the default implementation.", e);
- }
- }
- } catch (IllegalArgumentException ex) {
- // ignore
private static Settings getDefaultInstance() {
if (defaultImpl == null) {
// Create bootstrap implementation
//不带参数的DefaultSettings(),区别与DefaultPropertiesProvider中直接带default.properties参数
//不带参数就是默认为struts.propertes,并且加载struts.custom.properties所定义的properties文件
defaultImpl = new DefaultSettings();
// Create default implementation
try {
//STRUTS_CONFIGURATION为:struts.configuration
//在struts.proterties中查找struts.configuration的值,这个值必须是org.apache.struts2.config.Configuration接口的实现类
//所以我有个困惑就是在下面的转换当中怎么将Configuration转换成Setting类型的...
//这一点先放下了,有时间再研究
String className = get(StrutsConstants.STRUTS_CONFIGURATION);
if (!className.equals(defaultImpl.getClass().getName())) {
try {
// singleton instances shouldn't be built accessing request or session-specific context data
defaultImpl = (Settings) ObjectFactory.getObjectFactory().buildBean(Thread.currentThread().getContextClassLoader().loadClass(className), null);
} catch (Exception e) {
LOG.error("Settings: Could not instantiate the struts.configuration object, substituting the default implementation.", e);
}
}
} catch (IllegalArgumentException ex) {
// ignore
在2.1.6中去掉了第四步:init_ZeroConfiguration();
第五步是自定义的configProviders
- private void init_CustomConfigurationProviders() {
- //从这里可以看到可以将自定义的Provider定义在web.xml中FilterDispatcher的param中:configProviders
- String configProvs = initParams.get("configProviders");
- if (configProvs != null) {
- String[] classes = configProvs.split("\\s*[,]\\s*");
- for (String cname : classes) {
- try {
- Class cls = ClassLoaderUtils.loadClass(cname, this.getClass());
- ConfigurationProvider prov = (ConfigurationProvider)cls.newInstance();
- configurationManager.addConfigurationProvider(prov);
- }
- ...
- }
- }
- }
private void init_CustomConfigurationProviders() {
//从这里可以看到可以将自定义的Provider定义在web.xml中FilterDispatcher的param中:configProviders
String configProvs = initParams.get("configProviders");
if (configProvs != null) {
String[] classes = configProvs.split("\\s*[,]\\s*");
for (String cname : classes) {
try {
Class cls = ClassLoaderUtils.loadClass(cname, this.getClass());
ConfigurationProvider prov = (ConfigurationProvider)cls.newInstance();
configurationManager.addConfigurationProvider(prov);
}
...
}
}
}
第六步:init_FilterInitParameters
- //从这里可以看出struts.properties中的属性不仅可以在struts.xml中以constant形式定义,而且可以在FilterDispatcher的param中定义
- private void init_FilterInitParameters() {
- configurationManager.addConfigurationProvider(new ConfigurationProvider() {
- public void destroy() {}
- public void init(Configuration configuration) throws ConfigurationException {}
- public void loadPackages() throws ConfigurationException {}
- public boolean needsReload() { return false; }
- public void register(ContainerBuilder builder, LocatableProperties props) throws ConfigurationException {
- props.putAll(initParams);//在这里实现滴~
- }
- });
- }
//从这里可以看出struts.properties中的属性不仅可以在struts.xml中以constant形式定义,而且可以在FilterDispatcher的param中定义
private void init_FilterInitParameters() {
configurationManager.addConfigurationProvider(new ConfigurationProvider() {
public void destroy() {}
public void init(Configuration configuration) throws ConfigurationException {}
public void loadPackages() throws ConfigurationException {}
public boolean needsReload() { return false; }
public void register(ContainerBuilder builder, LocatableProperties props) throws ConfigurationException {
props.putAll(initParams);//在这里实现滴~
}
});
}
第七步:init_AliasStandardObjects,使用BeanSelectionProvider
这是将配置文件中定义的<bean>与实际的类相映射,就是注入bean的依赖关系,这部分以后有时候再研究Container
接下来是看怎样调用这些ConfigurationProviders
展开init_PreloadConfiguration()
- 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;
- }
- //再看getConfiguration()
- public synchronized Configuration getConfiguration() {
- if (configuration == null) {
- setConfiguration(new DefaultConfiguration(defaultFrameworkBeanName));
- try {
- //重点就是这个reloadContainer
- configuration.reloadContainer(getContainerProviders());
- } catch (ConfigurationException e) {
- setConfiguration(null);
- throw new ConfigurationException("Unable to load configuration.", e);
- }
- } else {
- conditionalReload();
- }
- return configuration;
- }
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;
}
//再看getConfiguration()
public synchronized Configuration getConfiguration() {
if (configuration == null) {
setConfiguration(new DefaultConfiguration(defaultFrameworkBeanName));
try {
//重点就是这个reloadContainer
configuration.reloadContainer(getContainerProviders());
} catch (ConfigurationException e) {
setConfiguration(null);
throw new ConfigurationException("Unable to load configuration.", e);
}
} else {
conditionalReload();
}
return configuration;
}
展开DefaultConfiguration中的reloadContainer
- public synchronized List<PackageProvider> reloadContainer(List<ContainerProvider> providers) throws ConfigurationException {
- packageContexts.clear();
- loadedFileNames.clear();
- List<PackageProvider> packageProviders = new ArrayList<PackageProvider>();
- //Struts2(xwork2)用Container来完成依赖注入的功能
- //首先初始化一个ContainerBuilder,再由builder来保存接口与实现类或工厂类的对应关系
- //然后通过builder.create(boolean)方法产生container
- //由container.getInstance(Class);就可以得到接口的实现实例了
- //这一部分比较复杂,后面研究完成了,会单独拿出来讲,这里先弄清楚Xwork依赖注入的实现步骤就可以了
- ContainerProperties props = new ContainerProperties();
- ContainerBuilder builder = new ContainerBuilder();
- for (final ContainerProvider containerProvider : providers)
- {
- //循环调用ConfigurationProvider的init和register方法,明白了吧,在这里统一循环调用
- containerProvider.init(this);
- containerProvider.register(builder, props);
- }
- props.setConstants(builder);
- //注入依赖关系,在这里并不产生实例
- builder.factory(Configuration.class, new Factory<Configuration>() {
- public Configuration create(Context context) throws Exception {
- return DefaultConfiguration.this;
- }
- });
- ActionContext oldContext = ActionContext.getContext();
- try {
- // Set the bootstrap container for the purposes of factory creation
- Container bootstrap = createBootstrapContainer();
- setContext(bootstrap);
- //create已经注入依赖关系的Container
- container = builder.create(false);
- setContext(container);
- objectFactory = container.getInstance(ObjectFactory.class);
- // Process the configuration providers first
- for (final ContainerProvider containerProvider : providers)
- {
- if (containerProvider instanceof PackageProvider) {
- container.inject(containerProvider);
- //调用PackageProvider的loadPackages()方法,这里主要是针对XmlConfigurationProvider和StrutsXmlConfigurationProvider
- ((PackageProvider)containerProvider).loadPackages();
- packageProviders.add((PackageProvider)containerProvider);
- }
- }
- // Then process any package providers from the plugins
- Set<String> packageProviderNames = container.getInstanceNames(PackageProvider.class);
- if (packageProviderNames != null) {
- for (String name : packageProviderNames) {
- PackageProvider provider = container.getInstance(PackageProvider.class, name);
- provider.init(this);
- provider.loadPackages();
- packageProviders.add(provider);
- }
- }
- rebuildRuntimeConfiguration();
- } finally {
- if (oldContext == null) {
- ActionContext.setContext(null);
- }
- }
- return packageProviders;
- }
public synchronized List<PackageProvider> reloadContainer(List<ContainerProvider> providers) throws ConfigurationException {
packageContexts.clear();
loadedFileNames.clear();
List<PackageProvider> packageProviders = new ArrayList<PackageProvider>();
//Struts2(xwork2)用Container来完成依赖注入的功能
//首先初始化一个ContainerBuilder,再由builder来保存接口与实现类或工厂类的对应关系
//然后通过builder.create(boolean)方法产生container
//由container.getInstance(Class);就可以得到接口的实现实例了
//这一部分比较复杂,后面研究完成了,会单独拿出来讲,这里先弄清楚Xwork依赖注入的实现步骤就可以了
ContainerProperties props = new ContainerProperties();
ContainerBuilder builder = new ContainerBuilder();
for (final ContainerProvider containerProvider : providers)
{
//循环调用ConfigurationProvider的init和register方法,明白了吧,在这里统一循环调用
containerProvider.init(this);
containerProvider.register(builder, props);
}
props.setConstants(builder);
//注入依赖关系,在这里并不产生实例
builder.factory(Configuration.class, new Factory<Configuration>() {
public Configuration create(Context context) throws Exception {
return DefaultConfiguration.this;
}
});
ActionContext oldContext = ActionContext.getContext();
try {
// Set the bootstrap container for the purposes of factory creation
Container bootstrap = createBootstrapContainer();
setContext(bootstrap);
//create已经注入依赖关系的Container
container = builder.create(false);
setContext(container);
objectFactory = container.getInstance(ObjectFactory.class);
// Process the configuration providers first
for (final ContainerProvider containerProvider : providers)
{
if (containerProvider instanceof PackageProvider) {
container.inject(containerProvider);
//调用PackageProvider的loadPackages()方法,这里主要是针对XmlConfigurationProvider和StrutsXmlConfigurationProvider
((PackageProvider)containerProvider).loadPackages();
packageProviders.add((PackageProvider)containerProvider);
}
}
// Then process any package providers from the plugins
Set<String> packageProviderNames = container.getInstanceNames(PackageProvider.class);
if (packageProviderNames != null) {
for (String name : packageProviderNames) {
PackageProvider provider = container.getInstance(PackageProvider.class, name);
provider.init(this);
provider.loadPackages();
packageProviders.add(provider);
}
}
rebuildRuntimeConfiguration();
} finally {
if (oldContext == null) {
ActionContext.setContext(null);
}
}
return packageProviders;
}