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()

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