struts2_源碼學習_Dispatcher(2)

續:Container

目錄

初始容器bootstrap

真正容器container

運行時配置信息

其他


上一篇文章已經介紹完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參數)

bootstrap.inject()

bootstrap注入成功

真正容器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的內容: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());
            }
        }
    }

我們可以看到結果:

runtimeConfiguration

至此,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()

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章