目錄
上一篇文章已經介紹完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()