`

Struts2源码阅读(四)_Dispatcher&ConfigurationProvider续

阅读更多

接下来第三步: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
           

 

在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);
                } 
				...
            }
        }
    }

 

第六步: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);//在这里实现滴~
            }
        });
    }	

 

第七步: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;
    }

 

展开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;
    }	

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics