目录
上一篇文章已经介绍完Container这个容器类,接下来我们继续Dispacher的初始化工作,也就是获得容器了。
Dispacher.init()
...
Container container = this.init_PreloadConfiguration();
container.inject(this);
...
Dispacher.init_PreloadConfiguration()
private Container init_PreloadConfiguration() {
return this.getContainer();
}
Dispacher.getContainer()
public Container getContainer() {
if (ContainerHolder.get() != null) {
return ContainerHolder.get();
} else {
//标志1
ConfigurationManager mgr = this.getConfigurationManager();
if (mgr == null) {
throw new IllegalStateException("The configuration manager shouldn't be null");
} else {
//标志2
Configuration config = mgr.getConfiguration();
if (config == null) {
throw new IllegalStateException("Unable to load configuration");
} else {
//标志3
Container container = config.getContainer();
ContainerHolder.store(container);
return container;
}
}
}
}
可以看到在经过前面的一系列初始化操作之后,我们已经将信息交付给ConfigurationManager管理了,所以主要调用了ConfigurationManager中getConfiguration()方法(标志1),再通过Configuration这个类获得Container(标志2)。
我们先看getConfiguration():
ConfigurationManager.getConfiguration()
public synchronized Configuration getConfiguration() {
if (this.configuration == null) {
this.setConfiguration(this.createConfiguration(this.defaultFrameworkBeanName));
try {
//主要代码
this.configuration.reloadContainer(this.getContainerProviders());
} catch (ConfigurationException var2) {
this.setConfiguration((Configuration)null);
throw new ConfigurationException("Unable to load configuration.", var2);
}
} else {
this.conditionalReload();
}
return this.configuration;
}
由于我们还没实例化获得configuration,所以执行了if代码块中的内容,实例化了一个DefaultConfiguration的对象,并调用了reloadContiner()(主要代码)。
DefaultConfiguration.reloadContainer()
public synchronized List<PackageProvider> reloadContainer(List<ContainerProvider> providers) throws ConfigurationException {
this.packageContexts.clear();
this.loadedFileNames.clear();
List<PackageProvider> packageProviders = new ArrayList();
DefaultConfiguration.ContainerProperties props = new DefaultConfiguration.ContainerProperties();
//Container的构建器
ContainerBuilder builder = new ContainerBuilder();
//初始容器
Container bootstrap = this.createBootstrapContainer(providers);
Iterator i$ = providers.iterator();
//对provider进行依赖注入,并且注册到builder中
while(i$.hasNext()) {
ContainerProvider containerProvider = (ContainerProvider)i$.next();
bootstrap.inject(containerProvider);
containerProvider.init(this);
containerProvider.register(builder, props);
}
//设置默认常量
props.setConstants(builder);
//将configuration注册到builder
builder.factory(Configuration.class, new Factory<Configuration>() {
public Configuration create(Context context) throws Exception {
return DefaultConfiguration.this;
}
public Class<? extends Configuration> type() {
return DefaultConfiguration.this.getClass();
}
});
ActionContext oldContext = ActionContext.getContext();
try {
this.setContext(bootstrap);
//构建container
this.container = builder.create(false);
this.setContext(this.container);
this.objectFactory = (ObjectFactory)this.container.getInstance(ObjectFactory.class);
Iterator i$ = providers.iterator();
//加载<package>信息
while(i$.hasNext()) {
ContainerProvider containerProvider = (ContainerProvider)i$.next();
if (containerProvider instanceof PackageProvider) {
this.container.inject(containerProvider);
((PackageProvider)containerProvider).loadPackages();
packageProviders.add((PackageProvider)containerProvider);
}
}
//查看是否还有其他PackageProvider
Set<String> packageProviderNames = this.container.getInstanceNames(PackageProvider.class);
Iterator i$ = packageProviderNames.iterator();
while(i$.hasNext()) {
String name = (String)i$.next();
PackageProvider provider = (PackageProvider)this.container.getInstance(PackageProvider.class, name);
provider.init(this);
provider.loadPackages();
packageProviders.add(provider);
}
//构建运行时配置
this.rebuildRuntimeConfiguration();
return packageProviders;
} finally {
if (oldContext == null) {
ActionContext.setContext((ActionContext)null);
}
}
}
初始容器bootstrap
在构造真正的Container之前会先创建一个初始的bootstrap容器:
protected Container createBootstrapContainer(List<ContainerProvider> providers) {
ContainerBuilder builder = new ContainerBuilder();
boolean fmFactoryRegistered = false;
Iterator i$ = providers.iterator();
while(i$.hasNext()) {
ContainerProvider provider = (ContainerProvider)i$.next();
if (provider instanceof FileManagerProvider) {
provider.register(builder, (LocatableProperties)null);
}
if (provider instanceof FileManagerFactoryProvider) {
provider.register(builder, (LocatableProperties)null);
fmFactoryRegistered = true;
}
}
builder.factory(ObjectFactory.class, Scope.SINGLETON);
...
//一堆builder.factory()
builder.factory(FileManager.class, "system", DefaultFileManager.class, Scope.SINGLETON);
if (!fmFactoryRegistered) {
builder.factory(FileManagerFactory.class, DefaultFileManagerFactory.class, Scope.SINGLETON);
}
builder.factory(ReflectionProvider.class, OgnlReflectionProvider.class, Scope.SINGLETON);
...
//一堆builder.factory()
builder.factory(ValueSubstitutor.class, EnvsValueSubstitutor.class, Scope.SINGLETON);
builder.constant("devMode", "false");
builder.constant("struts.devMode", "false");
builder.constant("logMissingProperties", "false");
builder.constant("enableOGNLEvalExpression", "false");
builder.constant("enableOGNLExpressionCache", "true");
builder.constant("reloadXmlConfiguration", "false");
builder.constant("struts.i18n.reload", "false");
return builder.create(true);
}
可以看到这个初始容器bootstrap首先加载了的是FileManager和FileManangerFactory的信息,然后会有一堆factory()方法,依旧是加载这些类的信息,还有constant()方法加载常量的信息,最终调用了create()方法。
ContainerBuilder.create()
public Container create(boolean loadSingletons) {
this.ensureNotCreated();
this.created = true;
//实例化container,具体可以看上一篇
ContainerImpl container = new ContainerImpl(new HashMap(this.factories));
if (loadSingletons) {
//实例化容器中的单例对象
container.callInContext(new ContextualCallable<Void>() {
public Void call(InternalContext context) {
Iterator i$ = ContainerBuilder.this.singletonFactories.iterator();
while(i$.hasNext()) {
InternalFactory<?> factory = (InternalFactory)i$.next();
factory.create(context);
}
return null;
}
});
}
//实例化 早期可实例化的对象
container.callInContext(new ContextualCallable<Void>() {
public Void call(InternalContext context) {
Iterator i$ = ContainerBuilder.this.earlyInitializableFactories.iterator();
while(i$.hasNext()) {
InternalFactory<?> factory = (InternalFactory)i$.next();
factory.create(context);
}
return null;
}
});
container.injectStatics(this.staticInjections);
return container;
}
具体的可以参考上一篇Container,这里就不再深入。初始容器bootStrap就完成,它包含了的应该是接下来真正容器所需的对象,所以功能应该就是为真正容器container提供注入功能。下面例子验证一下:(观察objectFactory和fileManager参数)
真正容器container
接下来的工作就是构建真正的容器container了。
Iterator i$ = providers.iterator();
//对provider进行依赖注入,并且注册到builder中
while(i$.hasNext()) {
ContainerProvider containerProvider = (ContainerProvider)i$.next();
bootstrap.inject(containerProvider);
containerProvider.init(this);
containerProvider.register(builder, props);
}
//设置默认常量
props.setConstants(builder);
//将configuration注册到builder
builder.factory(Configuration.class, new Factory<Configuration>() {
public Configuration create(Context context) throws Exception {
return DefaultConfiguration.this;
}
public Class<? extends Configuration> type() {
return DefaultConfiguration.this.getClass();
}
});
ActionContext oldContext = ActionContext.getContext();
try {
this.setContext(bootstrap);
//构建container
this.container = builder.create(false);
this.setContext(this.container);
this.objectFactory = (ObjectFactory)this.container.getInstance(ObjectFactory.class);
Iterator i$ = providers.iterator();
//加载<package>信息
while(i$.hasNext()) {
ContainerProvider containerProvider = (ContainerProvider)i$.next();
if (containerProvider instanceof PackageProvider) {
this.container.inject(containerProvider);
((PackageProvider)containerProvider).loadPackages();
packageProviders.add((PackageProvider)containerProvider);
}
}
//查看是否还有其他PackageProvider
Set<String> packageProviderNames = this.container.getInstanceNames(PackageProvider.class);
Iterator i$ = packageProviderNames.iterator();
while(i$.hasNext()) {
String name = (String)i$.next();
PackageProvider provider = (PackageProvider)this.container.getInstance(PackageProvider.class, name);
provider.init(this);
//最终保存在configuration的
//protected Map<String, PackageConfig> packageContexts中
provider.loadPackages();
packageProviders.add(provider);
}
this.rebuildRuntimeConfiguration();
return packageProviders;
} finally {
if (oldContext == null) {
ActionContext.setContext((ActionContext)null);
}
}
我们可以看看加载<package>信息之后packageContexts的内容:
可以看到和我们在struts.xml中配置的信息是一样的。具体的过程我们就不深入了(也就是解析然后保存的过程)。
运行时配置信息
最后的工作就是:
this.rebuildRuntimeConfiguration();
public void rebuildRuntimeConfiguration() {
this.runtimeConfiguration = this.buildRuntimeConfiguration();
}
protected synchronized RuntimeConfiguration buildRuntimeConfiguration() throws ConfigurationException {
Map<String, Map<String, ActionConfig>> namespaceActionConfigs = new LinkedHashMap();
Map<String, String> namespaceConfigs = new LinkedHashMap();
Iterator i$ = this.packageContexts.values().iterator();
while(true) {
PackageConfig packageConfig;
do {
if (!i$.hasNext()) {
PatternMatcher<int[]> matcher = (PatternMatcher)this.container.getInstance(PatternMatcher.class);
return new DefaultConfiguration.RuntimeConfigurationImpl(Collections.unmodifiableMap(namespaceActionConfigs), Collections.unmodifiableMap(namespaceConfigs), matcher);
}
packageConfig = (PackageConfig)i$.next();
} while(packageConfig.isAbstract());
String namespace = packageConfig.getNamespace();
Map<String, ActionConfig> configs = (Map)namespaceActionConfigs.get(namespace);
if (configs == null) {
configs = new LinkedHashMap();
}
Map<String, ActionConfig> actionConfigs = packageConfig.getAllActionConfigs();
Iterator i$ = actionConfigs.keySet().iterator();
while(i$.hasNext()) {
Object o = i$.next();
String actionName = (String)o;
ActionConfig baseConfig = (ActionConfig)actionConfigs.get(actionName);
((Map)configs).put(actionName, this.buildFullActionConfig(packageConfig, baseConfig));
}
namespaceActionConfigs.put(namespace, configs);
if (packageConfig.getFullDefaultActionRef() != null) {
namespaceConfigs.put(namespace, packageConfig.getFullDefaultActionRef());
}
}
}
我们可以看到结果:
至此,container的初始化操作也完成了。
其他
对于dispatcher剩下的初始化操作,从代码上看应该是:检查Web逻辑工作环境、初始化监听器、初始化错误控制器。以上工作仅从名字上的推测,实际工作过程我也没有再深入了,或许还有很多知识点没有挖掘,但是就到此为止吧。
public void init() {
...
this.init_CheckWebLogicWorkaround(container);
if (!dispatcherListeners.isEmpty()) {
Iterator i$ = dispatcherListeners.iterator();
while(i$.hasNext()) {
DispatcherListener l = (DispatcherListener)i$.next();
l.dispatcherInitialized(this);
}
}
this.errorHandler.init(this.servletContext);
} catch (Exception var4) {
LOG.error("Dispatcher initialization failed", var4);
throw new StrutsException(var4);
}
}
init收尾
在Dispatcher初始化操作之后,我们可以看到StrutsPrepareAndExecuteFilter的init()的大部分工作已经完成,剩下:
init.initStaticContentLoader(config, dispatcher);
this.prepare = this.createPrepareOperations(dispatcher);
this.execute = this.createExecuteOperations(dispatcher);
this.excludedPatterns = init.buildExcludedPatternsList(dispatcher);
this.postInit(dispatcher, filterConfig);
关于prepare和execute,在这里只是返回了PrepareOperation和ExecuteOperation的对象,我们还是在StrutsPrepareAndExecuteFilter的dofilter()操作中详细讲解,而关于excludedPatterns,我们需要知道的是:
struts.action.excludePattern
public List<Pattern> buildExcludedPatternsList(Dispatcher dispatcher) {
return this.buildExcludedPatternsList((String)dispatcher.getContainer().getInstance(String.class, "struts.action.excludePattern"));
}
也就是获得 <constant name ="struts.action.excludePattern" value=""> 对应的信息。作用是:
struts.action.excludePattern 设置struts所排除的url(通过正则表达式匹配,支持多个,以逗号隔开。对应的就是patterns.split(",") ).。
private List<Pattern> buildExcludedPatternsList(String patterns) {
if (null != patterns && patterns.trim().length() != 0) {
List<Pattern> list = new ArrayList();
String[] tokens = patterns.split(",");
String[] arr$ = tokens;
int len$ = tokens.length;
for(int i$ = 0; i$ < len$; ++i$) {
String token = arr$[i$];
list.add(Pattern.compile(token.trim()));
}
return Collections.unmodifiableList(list);
} else {
return null;
}
}
好了。终于把第一个主要方法的逻辑和部分源码搞清楚了。接下来的就是dofilter()了。
Next:dofilter()