struts2源碼分析(三)(初始化)(上)

3、所有需要解析的配置文件的解析類全部放入ConfigurationManager中的containerProviders中之後
 1:Container container = init_PreloadConfiguration();
 這段代碼,負責創建一個container對象,並初始化所有需要配置的文件信息;
 首先,該方法屬於Dispatcher中的方法,該方法的主要內容如下:

 /**
     * 加載前進行的配置初始化
     * @return
     */
    private Container init_PreloadConfiguration() {
     //獲取configuration
        ①Configuration config = configurationManager.getConfiguration();
        //從configuration中獲取container的一個實例
        ②Container container = config.getContainer();
        //獲取是否配置了國際化
        ③boolean reloadi18n = Boolean.valueOf(container.getInstance(String.class, StrutsConstants.STRUTS_I18N_RELOAD));
        //定義是否需要重新裝載資源綁定
        ④LocalizedTextUtil.setReloadBundles(reloadi18n);

        return container;
    }

 ①Configuration config = configurationManager.getConfiguration();
 調用ConfigurationManager的getConfiguration()方法獲取一個Configuration的實例,該方法的主要內容如下:

 /**
     * 獲取當前的xwork配置類。順便一個DefaultConfiguration的實體對象將被返回
     */
    public synchronized Configuration getConfiguration() {
        //系統首次運行時,該對象爲空
     if (configuration == null) {
      //創建一個新的DefaultConfiguration對象,並用其初始化Configuration
            setConfiguration(createConfiguration(defaultFrameworkBeanName));
            try {
             //調用DefaultConfiguration對象的reloadContainer方法;加載、解析所有配置文件
                configuration.reloadContainer(getContainerProviders());
            } catch (ConfigurationException e) {
                setConfiguration(null);
                throw new ConfigurationException("Unable to load configuration.", e);
            }
        } else {
         //重新加載配置文件如果配置文件裏面指明要重新加載
            conditionalReload(configuration.getContainer());
        }
     //返回這個configuration實例
        return configuration;
    }

 代碼setConfiguration(createConfiguration(defaultFrameworkBeanName));
 其中createConfiguration(defaultFrameworkBeanName)的具體代碼如下

/**
     * 創建一個DefaultConfiguration對象
     * @param beanName 此時beanName爲struts
     * @return
     */
    protected Configuration createConfiguration(String beanName) {
        return new DefaultConfiguration(beanName);
    } 

 在該方法裏,調用DefaultConfiguration的構造方法如下:

 /**
     * 構造方法,傳遞一個DefaultBeanName;
     * 如果沒傳遞的話,默認設置爲xwork
     * @param defaultBeanName
     */
    public DefaultConfiguration(String defaultBeanName) {
        this.defaultFrameworkBeanName = defaultBeanName;
    }

 在這裏設置了DefaultConfiguration的protected String defaultFrameworkBeanName;
 上述createConfiguration(String beanName)返回了一個DefaultConfiguration的實例,
 此時再調用ConfigurationManager中的setConfiguration把新實例化的DefaultConfiguration填充變量,該方法的具體代碼如下:

 /**
     * 通過傳遞過來的參數DefaultConfiguration初始化configuration
     * @param configuration
     */
    public synchronized void setConfiguration(Configuration configuration) {
        this.configuration = configuration;
    }

 此時初始化

protected Configuration configuration;//這個變量爲DefaultConfiguration 

 然後調用實例化之後的configuration的reloadContainer(getContainerProviders())方法,在該方法內部負責對配置文件進行加載和解析
 首先調用ConfigurationManager的getContainerProviders()返回containerProviders這個實例具體代碼如下

 /**
     * 獲取當前ConfigurationManager中包含的provider對象
     * @return the list of registered ConfigurationProvider objects
     * @see ConfigurationProvider
     */
    public List<ContainerProvider> getContainerProviders() {
        providerLock.lock();
        try {
         //理論上,不出意外的話,將直接返回containerProviders對象
            if (containerProviders.size() == 0) {
                containerProviders.add(new XWorkConfigurationProvider());//該類主要加載bean
                containerProviders.add(new XmlConfigurationProvider("xwork.xml", false));//加載xwork配置解析provider
            }

            return containerProviders;
        } finally {
            providerLock.unlock();
        }
    }

 此時返回containerProviders這個實例
 然後調用configuration的reloadContainer(List<ContainerProvider> containerProviders)方法,在這個方法裏面,對所有的配置信息進行了解析該方法的具體內容如下:

 /**
     * @throws ConfigurationException
     */
    public synchronized List<PackageProvider> reloadContainer(List<ContainerProvider> providers) throws ConfigurationException {
        1)packageContexts.clear();//清空packageContexts
        2)loadedFileNames.clear();//清空loadedFileNames
        3)List<PackageProvider> packageProviders = new ArrayList<PackageProvider>();

        4)ContainerProperties props = new ContainerProperties();//創建一個容器配置管理類,當前內部類
        5)ContainerBuilder builder = new ContainerBuilder();//創建一個ContainerBuilder對象
        6)Container bootstrap = createBootstrapContainer();//實例化一個Container對象,該對象是ContainerImpl的一個實例
        //循環每一個ContainterProvider,將他們各自對應的容器配置元素註冊到ContainerBuilder中去,
        //這裏,首先加載provider中的配置
        for (final ContainerProvider containerProvider : providers)
        {
   //containerProvider進行依賴注入,這部分代碼放在後面的struts2的依賴注入進行介紹
            7)bootstrap.inject(containerProvider);
            //這裏對於資源文件的處理分兩步走
            //當前的this指DefaultConfiguration這個對象
            8)containerProvider.init(this);//第一步是初始化,即完成格式轉換,如xml格式的轉換爲 document對象集合.
            //providers中存放的數據有以下內容:
            /**
             * 1、DefaultPropertiesProvider(default.properties),這個類的register運行結束之後,參數全部放入了props裏面
             * 2、StrutsXmlConfigurationProvider(struts-defaults.xml);這個類中constant放入build中,bean放入props中
             * 3、StrutsXmlConfigurationProvider(struts-plugin.xml);這個類中constant放入build中,bean放入props中
             * 4、StrutsXmlConfigurationProvider(struts.xml);這個類中constatn放入build中,bean放入props中
             * 5、LegacyPropertiesConfigurationProvider;這個類中需要配置的參數放入build中
             * 6、加載用戶配置的文件,一般情況下,未添加
             * 7、init_FilterInitParameters(添加在web.xml的Filter中配置的常量);把web.xml中的fileter中的參數放入props中
             * 8、BeanSelectionProvider;把配置放入builder中的factories中
             */
            9)containerProvider.register(builder, props);//第二步是將資源文件中配置的對象註冊到容器構造者對象中去。
        }
        //把props中的參數放入builder中
        10)props.setConstants(builder);
        //在builder中添加一個Configuration
        11)builder.factory(Configuration.class, new Factory<Configuration>() {
            public Configuration create(Context context) throws Exception {
                return DefaultConfiguration.this;
            }
        });

        //獲取當前線程的ActionContext
        12)ActionContext oldContext = ActionContext.getContext();
        try {
            // Set the bootstrap container for the purposes of factory creation

            13)setContext(bootstrap);
            14)container = builder.create(false);
            15)setContext(container);
            16)objectFactory = container.getInstance(ObjectFactory.class);//獲取一個objectFactory實例

            // Process the configuration providers first
            // 首先執行providers配置
            for (final ContainerProvider containerProvider : providers)
            {
             /**
              * 解析xml中配置的package元素
              */
                if (containerProvider instanceof PackageProvider) {
                    17)container.inject(containerProvider);//進行依賴注入,這部分代碼放在後面的struts2的依賴注入進行介紹
                    /**
                     * 1、DefaultPropertiesProvider(default.properties),這個類的loadPackages()方法不執行任何操作
                     * 2、StrutsXmlConfigurationProvider(struts-defaults.xml);這個類中的loadPackages()方法執行的結果解析了配置文件中的package元素並放入DefaultConfiguration元素的packageContexts中
                     * 3、StrutsXmlConfigurationProvider(struts-plugin.xml);這個類中的loadPackages()方法執行的結果解析了配置文件中的package元素並放入DefaultConfiguration元素的packageContexts中
                     * 4、StrutsXmlConfigurationProvider(struts.xml);這個類中的loadPackages()方法執行的結果解析了配置文件中的package元素並放入DefaultConfiguration元素的packageContexts中
                     * 5、LegacyPropertiesConfigurationProvider;這個類的loadPackages()方法不執行任何操作
                     * 6、加載用戶配置的文件,一般情況下,未添加
                     * 7、init_FilterInitParameters;這個類的loadPackages()方法不執行任何操作
                     * 8、BeanSelectionProvider;這個類的loadPackages()方法不執行任何操作
                     */
                    18)((PackageProvider)containerProvider).loadPackages();//調用loadPackages方法
                    19)packageProviders.add((PackageProvider)containerProvider);
                }
            }

            // Then process any package providers from the plugins
            //讓後執行plugins中的package providers
            20)Set<String> packageProviderNames = container.getInstanceNames(PackageProvider.class);
            if (packageProviderNames != null) {
                for (String name : packageProviderNames) {
                    21)PackageProvider provider = container.getInstance(PackageProvider.class, name);
                    22)provider.init(this);
                    23)provider.loadPackages();
                    24)packageProviders.add(provider);
                }
            }

            25)rebuildRuntimeConfiguration();
        } finally {
            if (oldContext == null) {
                26)ActionContext.setContext(null);
            }
        }
        27)return packageProviders;
    }

  1)packageContexts.clear();//清空packageContexts
  該DefaultConfiguration中有

protected Map<String, PackageConfig> packageContexts = new LinkedHashMap<String, PackageConfig>();


  這麼一個屬性在第一次加載時,先把這個屬性中的內容清空
  map裏面的PackageConfig(com.opensymphony.xwork2.config.entities)這個類是一個package的配置類,該類在xml的配置文件中,相當於package標籤。該類的具體作用和用法將在下面講到
  2)loadedFileNames.clear();//清空loadedFileNames,該參數用於記錄已經加載的文件名
  該DefaultConfiguration中有

 protected Set<String> loadedFileNames = new TreeSet<String>();這麼一個屬性。在第一次加載時,先把這個屬性中的內容清空 

  3)List<PackageProvider> packageProviders = new ArrayList<PackageProvider>();
  創建一個PackageProvider(com.opensymphony.xwork2.config)的list;該PackageProvider是一個接口,該接口的主要內容如下

public interface PackageProvider {
    
    /**
     * 初始化配置信息
     * @param configuration The configuration
     * @throws ConfigurationException If anything goes wrong
     */
    public void init(Configuration configuration) throws ConfigurationException;
    
    /**
     * 告知該packageProvider是否需要重新加載
     *
     * @return <tt>true</tt>, whether the PackageProvider should reload its configuration, <tt>false</tt>otherwise.
     */
    public boolean needsReload();

    /**
     * 爲配置加載該packageProvider
     * @throws ConfigurationException
     */
    public void loadPackages() throws ConfigurationException;
    
  }  

  該接口定義了3個方法,分別爲init(Configuration configuration),needsReload(),loadPackages()
  4)ContainerProperties props = new ContainerProperties();//創建一個容器配置管理類,當前內部類
  創建一個ContainerProperties(當前DefaultConfiguration的內部類)的類,該類的主要代碼如下

 /**
     * 容器配置類
     * 該類繼承自LoctableProperites
     * @author Administrator
     *
     */
    class ContainerProperties extends LocatableProperties {
        private static final long serialVersionUID = -7320625750836896089L;

        @Override
        public Object setProperty(String key, String value) {
            String oldValue = getProperty(key);
            if (LOG.isInfoEnabled() && oldValue != null && !oldValue.equals(value) && !defaultFrameworkBeanName.equals(oldValue)) {
                LOG.info("Overriding property "+key+" - old value: "+oldValue+" new value: "+value);
            }
            return super.setProperty(key, value);
        }

        /**
         * 把builder中的
         * @param builder
         */
        public void setConstants(ContainerBuilder builder) {
            for (Object keyobj : keySet()) {
                String key = (String)keyobj;
    //這裏調用了builder的方法,將在後面進行介紹
                builder.factory(String.class, key,
                        new LocatableConstantFactory<String>(getProperty(key), getPropertyLocation(key)));
            }
        }
    }

 該類繼承自LocatableProperties(com.opensymphony.xwork2.util.location)這個類繼承了Properties類,並實現了Locatable(com.opensymphony.xwork2.util.location)接口,
    Locatable接口的主要內容如下:

 public interface Locatable {
  /**
   * 得到這個對象的地址
   * @return 返回對象創建的地址
   */
  public Location getLocation();
 }

 5)ContainerBuilder builder = new ContainerBuilder();//創建一個ContainerBuilder對象
 調用ContainerBuilder(com.opensymphony.xwork2.inject)的默認無參構造方法,該方法具體內容如下:

 /**
    * 創建一個新的builder.
    */
   public ContainerBuilder() {
  // 在當前容器中作爲默認容器的實現
  factories.put(Key.newInstance(Container.class, Container.DEFAULT_NAME), CONTAINER_FACTORY);

  // 注入的注入成員的日誌記錄
  factories.put(Key.newInstance(Logger.class, Container.DEFAULT_NAME), LOGGER_FACTORY);
   }  

 在該ContainerBuilder中有一個常量

final Map<Key<?>, InternalFactory<?>> factories = new HashMap<Key<?>, InternalFactory<?>>();

 該常量是構建容器所必須的。其內容組成是與具體運行環境有關,既有來自struts2框架本身的配置所提供的一些組成部分,又有來自客戶項目的配置數據提供的組成部分
 其中Key中包含的是類的類型,名稱和哈希值。InternalFactory代表的是生成類的工廠對象,調用其中的factory方法,就可以生成相應的對象
 Key(com.opensymphony.xwork2.inject)該類的代碼如下:

/**
  * 依賴映射的關鍵。所需的類型和名稱的唯一性標識。
  */
 class Key<T> {

   final Class<T> type;//類型
   final String name;//名稱
   final int hashCode;//哈希值

   private Key(Class<T> type, String name) {
  if (type == null) {
    throw new NullPointerException("Type is null.");
  }
  if (name == null) {
    throw new NullPointerException("Name is null.");
  }

  this.type = type;
  this.name = name;

  hashCode = type.hashCode() * 31 + name.hashCode();
   }

   Class<T> getType() {
  return type;
   }

   String getName() {
  return name;
   }

   @Override
   public int hashCode() {
  return hashCode;
   }

   @Override
   public boolean equals(Object o) {
  if (!(o instanceof Key)) {
    return false;
  }
  if (o == this) {
    return true;
  }
  Key other = (Key) o;
  return name.equals(other.name) && type.equals(other.type);
   }

   @Override
   public String toString() {
  return "[type=" + type.getName() + ", name='" + name + "']";
   }

   static <T> Key<T> newInstance(Class<T> type, String name) {
  return new Key<T>(type, name);
   }
 } 

 InternalFactory(com.opensymphony.xwork2.inject)是一個接口,該接口的主要內容如下:

/**
  * 創建將要被注入的對象的實例化工廠
  */
 interface InternalFactory<T> extends Serializable {

   /**
    * 創建一個將要被注入的對象
    *
    * @param context of this injection
    * @return instance 將要被注入的類的實例
    */
   T create(InternalContext context);
 } 

 InternalContext(com.opensymphony.xwork2.inject)該類用於協調和支持循環依賴注入;該類的代碼如下

 /**
  * 內部上下文。用於協調和支持循環依賴注入。
  */
 class InternalContext {

   final ContainerImpl container;
   final Map<Object, ConstructionContext<?>> constructionContexts = new HashMap<Object, ConstructionContext<?>>();
   Scope.Strategy scopeStrategy;
   ExternalContext<?> externalContext;

   InternalContext(ContainerImpl container) {
  this.container = container;
   }

   public Container getContainer() {
  return container;
   }

   ContainerImpl getContainerImpl() {
  return container;
   }

   Scope.Strategy getScopeStrategy() {
  if (scopeStrategy == null) {
    scopeStrategy = (Scope.Strategy) container.localScopeStrategy.get();

    if (scopeStrategy == null) {
   throw new IllegalStateException("Scope strategy not set. "
    + "Please call Container.setScopeStrategy().");
    }
  }

  return scopeStrategy;
   }

   @SuppressWarnings("unchecked")
   <T> ConstructionContext<T> getConstructionContext(Object key) {
  ConstructionContext<T> constructionContext =
   (ConstructionContext<T>) constructionContexts.get(key);
  if (constructionContext == null) {
    constructionContext = new ConstructionContext<T>();
    constructionContexts.put(key, constructionContext);
  }
  return constructionContext;
   }

   @SuppressWarnings("unchecked")
   <T> ExternalContext<T> getExternalContext() {
  return (ExternalContext<T>) externalContext;
   }

   void setExternalContext(ExternalContext<?> externalContext) {
  this.externalContext = externalContext;
   }
 }

 在創建ContainerBuilder的時候

 factories.put(Key.newInstance(Container.class, Container.DEFAULT_NAME), CONTAINER_FACTORY);//在factories中添加一個創建Container的工廠

 這行代碼,向factory中添加了一個記錄:Key.newInstance(Container.class, Container.DEFAULT_NAME)爲一個Key的實例。其中Container.DEFAULT_NAME爲default
 CONTAINER_FACTORY(爲Container創建了一個工廠)爲:

 private static final InternalFactory<Container> CONTAINER_FACTORY = new InternalFactory<Container>() {
        public Container create(InternalContext context) {
          return context.getContainer();
        }
      };
 factories.put(Key.newInstance(Logger.class, Container.DEFAULT_NAME), LOGGER_FACTORY);//在factories中添加一個創建Logger的工廠

 LOGGER_FACTORY(爲Logger創建一個工廠)爲:

 private static final InternalFactory<Logger> LOGGER_FACTORY = new InternalFactory<Logger>() {
        public Logger create(InternalContext context) {
          Member member = context.getExternalContext().getMember();//(未分析)
          return member == null ? Logger.getAnonymousLogger() : Logger.getLogger(member.getDeclaringClass().getName());(未分析)
        }
      };

  6)Container bootstrap = createBootstrapContainer();//實例化一個Container對象,該對象是ContainerImpl的一個實例
  在這裏首先創建一個ContainerBuilder,利用該對象中的方法,初始化factories讓後再創建一個ContainerImpl返回
  該方法屬於DefaultConfiguration中的方法,其主要作用是創建一個Container對象。其代碼如下:

   /**
     * 創建一個Container對象
     * @return
     */
    protected Container createBootstrapContainer() {
     /**
      * 首先生成一個ContainerBuilder對象,調用register來實現對builder
      * 對象的factories成員變量的設置
      */
        ContainerBuilder builder = new ContainerBuilder();
        /**
         * 對框架的擴展點的實現,完成框架功能必須,因此也需要加載,否則容器無法正常起效,
         * 以下這些擴展點暫時未分析
         */
   //ObjectFactory負責創建核心框架對象
        builder.factory(ObjectFactory.class, Scope.SINGLETON);
        //其中FileManager訪問文件系統和文件的變化進行監測的基本接口
        //DefaultFileManager是FileManager接口的實現類
        builder.factory(FileManager.class, DefaultFileManager.class, Scope.SINGLETON);
        //未分析
        builder.factory(ReflectionProvider.class, OgnlReflectionProvider.class, Scope.SINGLETON);
        //ValueStackFactory值棧類接口,OgnlValueStackFactory值棧的實現類
        builder.factory(ValueStackFactory.class, OgnlValueStackFactory.class, Scope.SINGLETON);
        //xwork的類型轉換器
        builder.factory(XWorkConverter.class, Scope.SINGLETON);
        //xwork的類型轉換器
        builder.factory(XWorkBasicConverter.class, Scope.SINGLETON);
        //Collection類型轉換器
        builder.factory(TypeConverter.class, "collection",  CollectionConverter.class, Scope.SINGLETON);
        //Array類型轉換器
        builder.factory(TypeConverter.class, "array", ArrayConverter.class, Scope.SINGLETON);
        //Date類型轉換器
        builder.factory(TypeConverter.class, "date", DateConverter.class, Scope.SINGLETON);
        //Number類型轉換器
        builder.factory(TypeConverter.class, "number",  NumberConverter.class, Scope.SINGLETON);
        //String類型轉換器
        builder.factory(TypeConverter.class, "string", StringConverter.class, Scope.SINGLETON);
        //文本類型轉換器
        builder.factory(TextProvider.class, "system", DefaultTextProvider.class, Scope.SINGLETON);
        builder.factory(ObjectTypeDeterminer.class, DefaultObjectTypeDeterminer.class, Scope.SINGLETON);
        builder.factory(PropertyAccessor.class, CompoundRoot.class.getName(), CompoundRootAccessor.class, Scope.SINGLETON);
        builder.factory(OgnlUtil.class, Scope.SINGLETON);
        builder.constant("devMode", "false");
        builder.constant("logMissingProperties", "false");
        /**
         * 參數收集完成,通過create實現容器的創建
         */
        return builder.create(true);
    }

 在這個方法裏面涉及到ContainerBuilder的很多方法下面來對這些代碼進行分析:

 public final class ContainerBuilder {
   /**
    * 
    * factories是構建容器所必須的,但其內容組成是與具體運行環境有關,既有來自struts2框架本身的
    * 配置所提供的一些組成部分,又有來自客戶項目的配置數據提供的組成部分
    * 構造容器對象的時候的參數是一個個的鍵值對,
    * Key中包含的是類的類型,名稱和哈希值
    * InternalFactory代表的是生成類的工廠對象,調用其中的factory方法,就可以生成相應的對象
    */
   final Map<Key<?>, InternalFactory<?>> factories = new HashMap<Key<?>, InternalFactory<?>>();
   /**
    * 創建將要被注入的單例模式對象的列表
    */
   final List<InternalFactory<?>> singletonFactories = new ArrayList<InternalFactory<?>>();
   final List<Class<?>> staticInjections = new ArrayList<Class<?>>();
   boolean created;//是否已被創建
   boolean allowDuplicates = false;
   //container_factory
   private static final InternalFactory<Container> CONTAINER_FACTORY = new InternalFactory<Container>() {
   public Container create(InternalContext context) {
     return context.getContainer();
   }
    };
   //logger_factory
   private static final InternalFactory<Logger> LOGGER_FACTORY = new InternalFactory<Logger>() {
   public Logger create(InternalContext context) {
     Member member = context.getExternalContext().getMember();
     return member == null ? Logger.getAnonymousLogger() : Logger.getLogger(member.getDeclaringClass().getName());
   }
    };

   /**
    * 創建一個新的builder.
    */
   public ContainerBuilder() {
  // 在當前容器中作爲默認容器的實現
  factories.put(Key.newInstance(Container.class, Container.DEFAULT_NAME), CONTAINER_FACTORY);

  // 注入的注入成員的日誌記錄
  factories.put(Key.newInstance(Logger.class, Container.DEFAULT_NAME), LOGGER_FACTORY);
   }

   /**
    * 實現功能的主體。其它的factory方法主要是用來進行參數的適配和改造。
    */
   private <T> ContainerBuilder factory(final Key<T> key, InternalFactory<? extends T> factory, Scope scope) {
  ensureNotCreated();//用來確定該容器是否已經創建
  checkKey(key);//確認一個key是否已經映射了
  final InternalFactory<? extends T> scopedFactory = scope.scopeFactory(key.getType(), key.getName(), factory);//對工廠類的作用範圍進行包裝
  factories.put(key, scopedFactory);//把該工廠類放入factories中
  //如果該工廠類的作用範圍爲singleton
  if (scope == Scope.SINGLETON) {
    //把該工廠類進行裝飾,放入單例模式對象的列表
    singletonFactories.add(new InternalFactory<T>() {
   public T create(InternalContext context) {
     try {
    context.setExternalContext(ExternalContext.newInstance(null, key, context.getContainerImpl()));
    return scopedFactory.create(context);
     } finally {
    context.setExternalContext(null);
     }
   }
    });
  }
  return this;
   }
   
   /**
    * 確定一個key是否已經映射了
    */
   private void checkKey(Key<?> key) {
  if (factories.containsKey(key) && !allowDuplicates) {
    throw new DependencyException("Dependency mapping for " + key + " already exists.");
  }
   }

   /**
    * 映射一個factory通過給定的依賴類型和名稱
    *
    * @param type of dependency
    * @param name of dependency
    * @param factory creates objects to inject
    * @param scope scope of injected instances
    * @return this builder
    */
   public <T> ContainerBuilder factory(final Class<T> type, final String name, final Factory<? extends T> factory, Scope scope) {
    /**
     * 對傳入的factory對象進行裝飾
     */
  InternalFactory<T> internalFactory = new InternalFactory<T>() {

    public T create(InternalContext context) {
   try {
     Context externalContext = context.getExternalContext();
     return factory.create(externalContext);
   } catch (Exception e) {
     throw new RuntimeException(e);
   }
    }

    @Override
    public String toString() {
   return new LinkedHashMap<String, Object>() {{
     put("type", type);
     put("name", name);
     put("factory", factory);
   }}.toString();
    }
  };

  return factory(Key.newInstance(type, name), internalFactory, scope);
   }

   /**
    * 相當於調用factory(final Class<T> type, final String name, final Factory<? extends T> factory, Scope scope);
    */
   public <T> ContainerBuilder factory(Class<T> type, Factory<? extends T> factory, Scope scope) {
  return factory(type, Container.DEFAULT_NAME, factory, scope);
   }

   /**
    * 相當於調用factory(final Class<T> type, final String name, final Factory<? extends T> factory, Scope scope);
    */
   public <T> ContainerBuilder factory(Class<T> type, String name, Factory<? extends T> factory) {
  return factory(type, name, factory, Scope.DEFAULT);
   }

   /**
    * 相當於調用factory(final Class<T> type, final String name, final Factory<? extends T> factory, Scope scope);
    */
   public <T> ContainerBuilder factory(Class<T> type, Factory<? extends T> factory) {
  return factory(type, Container.DEFAULT_NAME, factory, Scope.DEFAULT);
   }

   /**
    * 映射一個給定依賴名字和類型的實現類,用container創建一個實例,遞歸依賴注入
    * @param type 依賴的類型
    * @param name 依賴的名稱
    * @param implementation 實現類
    * @param scope 注入的作用範圍
    * @return this builder
    */
   public <T> ContainerBuilder factory(final Class<T> type, final String name, final Class<? extends T> implementation, final Scope scope) {
  // 這個工廠創建一個給定實現類的實例
  //對給定的implementation進行裝飾
  InternalFactory<? extends T> factory = new InternalFactory<T>() {

    volatile ContainerImpl.ConstructorInjector<? extends T> constructor;

    @SuppressWarnings("unchecked")
    public T create(InternalContext context) {
   if (constructor == null) {
     this.constructor =
      context.getContainerImpl().getConstructor(implementation);
   }
   return (T) constructor.construct(context, type);
    }

    @Override
    public String toString() {
   return new LinkedHashMap<String, Object>() {{
     put("type", type);
     put("name", name);
     put("implementation", implementation);
     put("scope", scope);
   }}.toString();
    }
  };

  return factory(Key.newInstance(type, name), factory, scope);
   }

   /**
    * 映射一個給定依賴名字和類型的實現類,用container創建一個實例,遞歸依賴注入
    * <p>Sets scope to value from {@link Scoped} annotation on the
    * implementation class. Defaults to {@link Scope#DEFAULT} if no annotation
    * is found.
    *
    * @param type of dependency
    * @param name of dependency
    * @param implementation class
    * @return this builder
    */
   public <T> ContainerBuilder factory(final Class<T> type, String name, final Class<? extends T> implementation) {
  Scoped scoped = implementation.getAnnotation(Scoped.class);
  Scope scope = scoped == null ? Scope.DEFAULT : scoped.value();
  return factory(type, name, implementation, scope);
   }

   /**
    * 相當於調用 factory(final Class<T> type, String name, final Class<? extends T> implementation)
    */
   public <T> ContainerBuilder factory(Class<T> type, Class<? extends T> implementation) {
  return factory(type, Container.DEFAULT_NAME, implementation);
   }

   /**
    * 相當於調用 factory(final Class<T> type, String name, final Class<? extends T> implementation)
    */
   public <T> ContainerBuilder factory(Class<T> type) {
  return factory(type, Container.DEFAULT_NAME, type);
   }

   /**
    * 相當於調用 factory(final Class<T> type, String name, final Class<? extends T> implementation)
    */
   public <T> ContainerBuilder factory(Class<T> type, String name) {
  return factory(type, name, type);
   }

   /**
    * 相當於調用factory(final Class<T> type, final String name, final Class<? extends T> implementation, final Scope scope)
    */
   public <T> ContainerBuilder factory(Class<T> type, Class<? extends T> implementation, Scope scope) {
  return factory(type, Container.DEFAULT_NAME, implementation, scope);
   }

   /**
    * 相當於調用factory(final Class<T> type, final String name, final Class<? extends T> implementation, final Scope scope)
    */
   public <T> ContainerBuilder factory(Class<T> type, Scope scope) {
  return factory(type, Container.DEFAULT_NAME, type, scope);
   }

   /**
    * 相當於調用factory(final Class<T> type, final String name, final Class<? extends T> implementation, final Scope scope)
    */
   public <T> ContainerBuilder factory(Class<T> type, String name, Scope scope) {
  return factory(type, name, type, scope);
   }
   
   /**
    * 相當於調用alias(Class<T> type, String alias)
    */
   public <T> ContainerBuilder alias(Class<T> type, String alias) {
  return alias(type, Container.DEFAULT_NAME, alias);
   }
   
   /**
    * 映射一個已存在的工廠一個新的名字
    * 
    * @param type of dependency
    * @param name of dependency
    * @param alias of to the dependency
    * @return this builder
    */
   public <T> ContainerBuilder alias(Class<T> type, String name, String alias) {
  return alias(Key.newInstance(type, name), Key.newInstance(type, alias));
   }
   
   /**
    * 映射一個現有的依賴關係。並替換key爲aliasKey
    */
   private <T> ContainerBuilder alias(final Key<T> key, final Key<T> aliasKey) {
  ensureNotCreated();//判斷該容器是否已經被創建
  checkKey(aliasKey);//判斷該key是否已經存在
  
  //獲取factories中指定key的對象
  final InternalFactory<? extends T> scopedFactory = (InternalFactory<? extends T>)factories.get(key);
  //如果該對象不存在,拋出異常
  if (scopedFactory == null) {
   throw new DependencyException("Dependency mapping for " + key + " doesn't exists.");
  }
  //把新的key,和對象放入aliasKey中
  factories.put(aliasKey, scopedFactory);
  return this;
   }

   /**
    * 映射一個給定名稱的常量值
    */
   public ContainerBuilder constant(String name, String value) {
  return constant(String.class, name, value);
   }

   /**
    * 映射一個給定名稱的常量值
    */
   public ContainerBuilder constant(String name, int value) {
  return constant(int.class, name, value);
   }

   /**
    * 映射一個給定名稱的常量值
    */
   public ContainerBuilder constant(String name, long value) {
  return constant(long.class, name, value);
   }

   /**
    * 映射一個給定名稱的常量值
    */
   public ContainerBuilder constant(String name, boolean value) {
  return constant(boolean.class, name, value);
   }

   /**
    * 映射一個給定名稱的常量值
    */
   public ContainerBuilder constant(String name, double value) {
  return constant(double.class, name, value);
   }

   /**
    * 映射一個給定名稱的常量值
    */
   public ContainerBuilder constant(String name, float value) {
  return constant(float.class, name, value);
   }

   /**
    * 映射一個給定名稱的常量值
    */
   public ContainerBuilder constant(String name, short value) {
  return constant(short.class, name, value);
   }

   /**
    * 映射一個給定名稱的常量值
    */
   public ContainerBuilder constant(String name, char value) {
  return constant(char.class, name, value);
   }

   /**
    * 映射一個給定名稱的常量值
    */
   public ContainerBuilder constant(String name, Class value) {
  return constant(Class.class, name, value);
   }

   /**
    * 映射一個給定名稱的常量值
    */
   public <E extends Enum<E>> ContainerBuilder constant(String name, E value) {
  return constant(value.getDeclaringClass(), name, value);
   }

   /**
    * 映射一個給定名稱和類型的常量值.
    */
   private <T> ContainerBuilder constant(final Class<T> type, final String name, final T value) {
  //對給定值進行裝飾
  InternalFactory<T> factory = new InternalFactory<T>() {
    public T create(InternalContext ignored) {
   return value;
    }

    @Override
    public String toString() {
   return new LinkedHashMap<String, Object>() {
     {
    put("type", type);
    put("name", name);
    put("value", value);
     }
   }.toString();
    }
  };
  return factory(Key.newInstance(type, name), factory, Scope.DEFAULT);
   }

   /**
    * 在創建時,容器將注入靜態域和方法爲給定的類。
    * @param types 將被注入的靜態常量成員
    */
   public ContainerBuilder injectStatics(Class<?>... types) {
  staticInjections.addAll(Arrays.asList(types));
  return this;
   }

   /**
    * 如果factories中包含給定類型和名稱的值,則返回true
    */
   public boolean contains(Class<?> type, String name) {
  return factories.containsKey(Key.newInstance(type, name));
   }

   /**
    * 相當於調用contains(Class<?> type, String name)
    */
   public boolean contains(Class<?> type) {
  return contains(type, Container.DEFAULT_NAME);
   }

   /**
    * Creates a {@link Container} instance. Injects static members for classes
    * which were registered using {@link #injectStatics(Class...)}.
    * 創建一個Container實例。
    * 
    * @param loadSingletons 如果 boolean created(loadSingletons)值爲true 的話,先調用scope="singleton" 的對象工廠的create方法
    * @throws IllegalStateException if called more than once
    */
   public Container create(boolean loadSingletons) {
  ensureNotCreated();//判斷是否已經創建
  created = true;//設置created爲true
  final ContainerImpl container = new ContainerImpl(new HashMap<Key<?>, InternalFactory<?>>(factories));
  //把對象生命週期爲單實例的對象先創建出來.  
  if (loadSingletons) {
    container.callInContext(new ContainerImpl.ContextualCallable<Void>() {
   public Void call(InternalContext context) {
     for (InternalFactory<?> factory : singletonFactories) {
    factory.create(context);
     }
     return null;
   }
    });
  }
  //依賴注入
  container.injectStatics(staticInjections);
  //返回一個ContainerImpl實例對象
  return container;
   }

   /**
    * 現在我們只支持創造每一容器實例生成器。
    * 如果我們想支持創建每建造多個容器,我們要搬到一個“工廠”的模式,我們創建每個集裝箱廠實例。
    * 現在,一個工廠的實例將在所有容器共享,單身人士對容器時延遲加載,等。
    */
   private void ensureNotCreated() {
  if (created) {
    throw new IllegalStateException("Container already created.");
  }
   }
   
   public void setAllowDuplicates(boolean val) {
    allowDuplicates = val;
   }

   /**
    * Implemented by classes which participate in building a container.
    */
   public interface Command {

  /**
   * Contributes factories to the given builder.
   *
   * @param builder
   */
  void build(ContainerBuilder builder);
   }
 }

  7)bootstrap.inject(containerProvider);
containerProvider進行依賴注入,這部分代碼放在後面的struts2的依賴注入進行介紹 

  8)containerProvider.init(this);//這裏是比較核心的一個模塊
  首先確定當前的providers中有哪些記錄
  1:DefaultPropertiesProvider(default.properties)
  執行DefaultPropertiesProvider該類的init(Configuration configuration)方法
  該類的該方法如下:

 /**
     * 不用把該對象轉換成document對象
     */
    public void init(Configuration configuration) throws ConfigurationException {
    }

  2:StrutsXmlConfigurationProvider(struts-default.xml)
  該類沒有對init方法進行重寫,因此調用父類(XmlConfigurationProvider)的init方法

/**
     * @param configuration 爲DefaultConfiguration對象的一個實例
     */
    public void init(Configuration configuration) {
        this.configuration = configuration;//設置configuration
        this.includedFileNames = configuration.getLoadedFileNames();//此時爲空
        loadDocuments(configFileName);//第一次爲loadDocuments(struts-defaults.xml)
    } 
 /**
     * @param configFileName struts-default.xml
     */
    private void loadDocuments(String configFileName) {
        try {
            loadedFileUrls.clear();
            documents = loadConfigurationFiles(configFileName, null);//把*.xml轉換成document形式,並存放到documents中
        } catch (ConfigurationException e) {
            throw e;
        } catch (Exception e) {
            throw new ConfigurationException("Error loading configuration file " + configFileName, e);
        }
    }

 其中private Set<String> loadedFileUrls = new HashSet<String>();//已經加載的file的URL

/**
     * 返回*.xml的document形式結果
     * @param fileName struts-default.xml
     * @param includeElement null
     */
    private List<Document> loadConfigurationFiles(String fileName, Element includeElement) {
        List<Document> docs = new ArrayList<Document>();//創建一個新的List<dom>對象
        List<Document> finalDocs = new ArrayList<Document>();//再創建一個finalDocs的List<dom>對象
        if (!includedFileNames.contains(fileName)) {//如果includedFileNames不包含名爲fileName的對象
            if (LOG.isDebugEnabled()) {
                LOG.debug("Loading action configurations from: " + fileName);
            }
            //把該fileName添加到includedFileNames,防止重複添加
            includedFileNames.add(fileName);
            
            Iterator<URL> urls = null;
            InputStream is = null;

            IOException ioException = null;
            try {
             /**
              * 獲取fileName的URL
              */
                urls = getConfigurationUrls(fileName);
            } catch (IOException ex) {
                ioException = ex;
            }
            
            /**
             * 如果urls爲空,或urls.hasNext = true,則執行下面的代碼
             */
            if (urls == null || !urls.hasNext()) {
                if (errorIfMissing) {
                    throw new ConfigurationException("Could not open files of the name " + fileName, ioException);
                } else {
                    if (LOG.isInfoEnabled()) {
                    LOG.info("Unable to locate configuration files of the name "
                            + fileName + ", skipping");
                    }
                    return docs;//此時docs對象爲空
                }
            }
            //否則
            URL url = null;
            while (urls.hasNext()) {
                try {
                 //把fileName的URL傳遞給url
                    url = urls.next();
                    //fileManager對象爲DefaultFileManager,通過struts框架自動注入進來
     //根據URL加載指定的文件,並返回inputStream形式的結果
                    is = fileManager.loadFile(url);

                    InputSource in = new InputSource(is);

                    //設置此輸入源的系統標識符
                    in.setSystemId(url.toString());

                    /**
                     * 在docs中添加一個document
                     */
                    docs.add(DomHelper.parse(in, dtdMappings));
                } catch (XWorkException e) {
                    if (includeElement != null) {
                        throw new ConfigurationException("Unable to load " + url, e, includeElement);
                    } else {
                        throw new ConfigurationException("Unable to load " + url, e);
                    }
                } catch (Exception e) {
                    final String s = "Caught exception while loading file " + fileName;
                    throw new ConfigurationException(s, e, includeElement);
                } finally {
                    if (is != null) {
                        try {
                            is.close();
                        } catch (IOException e) {
                            LOG.error("Unable to close input stream", e);
                        }
                    }
                }
            }
            
            //對documents進行排序,通過order這個屬性
            Collections.sort(docs, new Comparator<Document>() {//(未分析)
                public int compare(Document doc1, Document doc2) {
                    return XmlHelper.getLoadOrder(doc1).compareTo(XmlHelper.getLoadOrder(doc2));
                }
            });

            /**
             * 對docs中的內容進行遍歷
             */
            for (Document doc : docs) {
                Element rootElement = doc.getDocumentElement();
                NodeList children = rootElement.getChildNodes();
                int childSize = children.getLength();//struts-default.xml中有72個child;
                //對xml進行解析,查看其所有子元素中是否包含include元素
                for (int i = 0; i < childSize; i++) {
                    Node childNode = children.item(i);

                    if (childNode instanceof Element) {
                     //獲取element
                        Element child = (Element) childNode;
                        //獲取element的name
                        final String nodeName = child.getNodeName();
                        //如果element==include
                        if ("include".equals(nodeName)) {
                            String includeFileName = child.getAttribute("file");
                            if (includeFileName.indexOf('*') != -1) {
                                // handleWildCardIncludes(includeFileName, docs, child);
                                ClassPathFinder wildcardFinder = new ClassPathFinder();
                                wildcardFinder.setPattern(includeFileName);
                                Vector<String> wildcardMatches = wildcardFinder.findMatches();
                                for (String match : wildcardMatches) {
                                    finalDocs.addAll(loadConfigurationFiles(match, child));
                                }
                            } else {
                                finalDocs.addAll(loadConfigurationFiles(includeFileName, child));//遞歸調用,把所有include加載到finalDocs
                            }
                        }
                    }
                }
                finalDocs.add(doc);
                loadedFileUrls.add(url.toString());
            }

            if (LOG.isDebugEnabled()) {
                LOG.debug("Loaded action configuration from: " + fileName);
            }
        }
        return finalDocs;
    }

 /**
     * 獲取fileName的Iterator<URL>
     * @param fileName
     * @return
     * @throws IOException
     */
    protected Iterator<URL> getConfigurationUrls(String fileName) throws IOException {
        return ClassLoaderUtil.getResources(fileName, XmlConfigurationProvider.class, false);
    }

至此,struts-default.xml已經轉換成一個document對象放入docs中,接下來調用register再對轉換好的docs中的內容進行解析

3:StrutsXmlConfigurationProvider(struts-plugin.xml)
  同2:
4:StrutsXmlConfigurationProvider(struts.xml)
  同2:

5:LegacyPropertiesConfigurationProvider
  該類的register中的代碼具體如下:

   /**
     * 註冊參數,把需要配置的參數放入builder對象的factories中
     */
    @SuppressWarnings("unchecked")
 public void register(ContainerBuilder builder, LocatableProperties props)throws ConfigurationException {
        
     //獲取一個Settings的實例
        final Settings settings = Settings.getInstance();
        
        loadSettings(props, settings);
        
        // Set default locale by lazily resolving the locale property as needed into a Locale object
        builder.factory(Locale.class, new Factory() {
            private Locale locale;

            public synchronized Object create(Context context) throws Exception {
                if (locale == null) {
                    String loc = context.getContainer().getInstance(String.class, StrutsConstants.STRUTS_LOCALE);
                    if (loc != null) {
                        StringTokenizer localeTokens = new StringTokenizer(loc, "_");
                        String lang = null;
                        String country = null;

                        if (localeTokens.hasMoreTokens()) {
                            lang = localeTokens.nextToken();
                        }

                        if (localeTokens.hasMoreTokens()) {
                            country = localeTokens.nextToken();
                        }
                        locale = new Locale(lang, country);
                    } else {
                        if (LOG.isInfoEnabled()) {
                            LOG.info("No locale define, substituting the default VM locale");
                        }
                        locale = Locale.getDefault();
                    }
                }
                return locale;
            }
        });
    }

6:用戶配置
  具體代碼具體分析
7:web.xml的filter中配置的參數

//把web.xml中配置的fileter中的參數放入props中
  public void register(ContainerBuilder builder, LocatableProperties props) throws ConfigurationException {
       props.putAll(initParams);
  }

8:BeanSelectionProvider

該類內部的register方法如下:

/**
     * 註冊
     */
    public void register(ContainerBuilder builder, LocatableProperties props) {
    	/**
    	 * 把這些配置放入builder的factories中
    	 */
        alias(ObjectFactory.class, StrutsConstants.STRUTS_OBJECTFACTORY, builder, props);
        alias(FileManager.class, StrutsConstants.STRUTS_FILEMANAGER, builder, props);
        alias(XWorkConverter.class, StrutsConstants.STRUTS_XWORKCONVERTER, builder, props);
        alias(TextProvider.class, StrutsConstants.STRUTS_XWORKTEXTPROVIDER, builder, props, Scope.DEFAULT);
        alias(ActionProxyFactory.class, StrutsConstants.STRUTS_ACTIONPROXYFACTORY, builder, props);
        alias(ObjectTypeDeterminer.class, StrutsConstants.STRUTS_OBJECTTYPEDETERMINER, builder, props);
        alias(ActionMapper.class, StrutsConstants.STRUTS_MAPPER_CLASS, builder, props);
        alias(MultiPartRequest.class, StrutsConstants.STRUTS_MULTIPART_PARSER, builder, props, Scope.DEFAULT);
        alias(FreemarkerManager.class, StrutsConstants.STRUTS_FREEMARKER_MANAGER_CLASSNAME, builder, props);
        alias(VelocityManager.class, StrutsConstants.STRUTS_VELOCITY_MANAGER_CLASSNAME, builder, props);
        alias(UrlRenderer.class, StrutsConstants.STRUTS_URL_RENDERER, builder, props);
        alias(ActionValidatorManager.class, StrutsConstants.STRUTS_ACTIONVALIDATORMANAGER, builder, props);
        alias(ValueStackFactory.class, StrutsConstants.STRUTS_VALUESTACKFACTORY, builder, props);
        alias(ReflectionProvider.class, StrutsConstants.STRUTS_REFLECTIONPROVIDER, builder, props);
        alias(ReflectionContextFactory.class, StrutsConstants.STRUTS_REFLECTIONCONTEXTFACTORY, builder, props);
        alias(PatternMatcher.class, StrutsConstants.STRUTS_PATTERNMATCHER, builder, props);
        alias(StaticContentLoader.class, StrutsConstants.STRUTS_STATIC_CONTENT_LOADER, builder, props);
        alias(UnknownHandlerManager.class, StrutsConstants.STRUTS_UNKNOWN_HANDLER_MANAGER, builder, props);
        alias(UrlHelper.class, StrutsConstants.STRUTS_URL_HELPER, builder, props);

        /**
         * 判斷props中的devMode是否爲true
         */
        if ("true".equalsIgnoreCase(props.getProperty(StrutsConstants.STRUTS_DEVMODE))) {
        	//設置國際化
            props.setProperty(StrutsConstants.STRUTS_I18N_RELOAD, "true");
            props.setProperty(StrutsConstants.STRUTS_CONFIGURATION_XML_RELOAD, "true");
            props.setProperty(StrutsConstants.STRUTS_FREEMARKER_TEMPLATES_CACHE, "false");
            props.setProperty(StrutsConstants.STRUTS_FREEMARKER_TEMPLATES_CACHE_UPDATE_DELAY, "0");
            // Convert struts properties into ones that xwork expects
            props.setProperty("devMode", "true");
        } else {
            props.setProperty("devMode", "false");
        }

        //把struts2的properties轉換成xwork的properties
        convertIfExist(props, StrutsConstants.STRUTS_LOG_MISSING_PROPERTIES, "logMissingProperties");
        convertIfExist(props, StrutsConstants.STRUTS_ENABLE_OGNL_EXPRESSION_CACHE, "enableOGNLExpressionCache");
        convertIfExist(props, StrutsConstants.STRUTS_ALLOW_STATIC_METHOD_ACCESS, "allowStaticMethodAccess");

        LocalizedTextUtil.addDefaultResourceBundle("org/apache/struts2/struts-messages");
        //加載用戶資源綁定
        loadCustomResourceBundles(props);
    }


在這個方法內部調用了該類的alias方法,該方法具體如下:

/**
     * 調用該類的alias(Class type, String key, ContainerBuilder builder, Properties props, Scope scope)方法,同時傳遞scope爲single
     * @param type
     * @param key
     * @param builder
     * @param props
     */
    void alias(Class type, String key, ContainerBuilder builder, Properties props) {
        alias(type, key, builder, props, Scope.SINGLETON);
    }

接着調用另一個alias方法,該方法具體如下:

/**
     * 把參數放入builder中
     * @param type class類型
     * @param key 
     * @param builder
     * @param props
     * @param scope
     */
    void alias(Class type, String key, ContainerBuilder builder, Properties props, Scope scope) {
    	//判斷builder中是否存在指定type的參數
        if (!builder.contains(type)) {
        	/**
        	 * 從props中獲取指定key和默認值的字符串
        	 */
            String foundName = props.getProperty(key, DEFAULT_BEAN_NAME);
            //檢測builder中是否包含該type和指定默認值的配置
            if (builder.contains(type, foundName)) {
                if (LOG.isInfoEnabled()) {
                    LOG.info("Choosing bean (#0) for (#1)", foundName, type.getName());
                }
                //重新加載到builder中
                builder.alias(type, foundName, Container.DEFAULT_NAME);
            } else {
                try {
                	//反射生成class
                    Class cls = ClassLoaderUtil.loadClass(foundName, this.getClass());
                    if (LOG.isDebugEnabled()) {
                        LOG.debug("Choosing bean (#0) for (#1)", cls.getName(), type.getName());
                    }
                    //把cls添加到builder中的factories中
                    builder.factory(type, cls, scope);
                } catch (ClassNotFoundException ex) {
                    // Perhaps a spring bean id, so we'll delegate to the object factory at runtime
                    if (LOG.isDebugEnabled()) {
                        LOG.debug("Choosing bean (#0) for (#1) to be loaded from the ObjectFactory", foundName, type.getName());
                    }
                    if (DEFAULT_BEAN_NAME.equals(foundName)) {
                        // Probably an optional bean, will ignore
                    } else {
                        if (ObjectFactory.class != type) {
                            builder.factory(type, new ObjectFactoryDelegateFactory(foundName, type), scope);
                        } else {
                            throw new ConfigurationException("Cannot locate the chosen ObjectFactory implementation: " + foundName);
                        }
                    }
                }
            }
        } else {
            if (LOG.isWarnEnabled()) {
        	    LOG.warn("Unable to alias bean type (#0), default mapping already assigned.", type.getName());
            }
        }
    }

ContainerBuilder的代碼在上面已經給出了分析,因此在這裏不對其方法再次進行介紹。

10)props.setConstants(builder);

調用ContainerProperties的setConstants(ContainerBuilder builder)方法,把props中的信息放入ContainerBuilder的factories中;具體代碼在上面已經展示過了

11)這行代碼調用了ContainerBuilder的factory方法,向其factories中添加了一個Configuration的工廠類,該類的實例化爲一個DefaultConfiguration對象

builder.factory(Configuration.class, new Factory<Configuration>() {
            public Configuration create(Context context) throws Exception {
                return DefaultConfiguration.this;
            }
        });
發佈了39 篇原創文章 · 獲贊 0 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章