Spring Ioc容器読書ノート

8662 ワード

Ioc容器初期化プロセス<
  • Ioc初期化の入り口はrefsh方法です.
  • public FileSystemXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent)
        throws BeansException {
    
    
        super(parent);
        setConfigLocations(configLocations);
        if (refresh) {
        refresh();
        }
        }
    このrefresh方法はIoc容器の正式な起動を示しています.その起動は以下の3つのステップに分けられます.
  • Resource位置付け(Resource Loaderモジュールが担当する)
  • BenDefinitionをロードし、解析を行います.定義されたビームをロードし、Ioc容器内部のデータ構造に解析します.このBeanDefinitionを通じて、Ioc容器はBeanの管理を実現します.
  • BenDefinition登録します.このプロセスはBeanDefinitionRegistryインターフェースを呼び出すことによって達成される.その本質は、解析されたBeanDefinitionをIoc容器のHashMapに入れることである.
  •     //DefaultListableBeanFactory  
        // Map of bean definition objects, keyed by bean name
            private final Map <String,BeanDefinition> beanDefinitionMap = new ConcurrentHashMap <String,BeanDefinition>();
    PS:ここではビーンDefinitionの登録とビーン依存注入の違いを強調します.
    BeanDefinitionの登録は、HashMapにBenDefinitionを入れるだけで完了します.依存の注入は、Ioc容器が起動するときに行われるものではない.ゲームビーンの実例の時だけです.
    依存注入をトリガします.この二つは独立の過程です.
  • BenDefinition Resource位置決め
  • 表示クラスAbstract BenDefinitionReader:
        public int loadBeanDefinitions(String location, Set
        <Resource> actualResources) throws BeanDefinitionStoreException {
            ResourceLoader resourceLoader = getResourceLoader();
            if (resourceLoader == null) {
            //...
            }
    
    
            if (resourceLoader instanceof ResourcePatternResolver) {
            // Resource pattern matching available.
            try {
            Resource[] resources = ((ResourcePatternResolver) resourceLoader).getResources(location);
            int loadCount = loadBeanDefinitions(resources);
            if (actualResources != null) {
            ...
            }
            }
    
    
            return loadCount;
            }
            catch (IOException ex) {
            //...
            }
            }
            else {
            //....
            }
            }
    キーはロカションによってResourceの場所を決めます.どうぞご覧ください.
        public Resource[] getResources(String locationPattern) throws IOException {
        Assert.notNull(locationPattern, "Location pattern must not be null");
        if (locationPattern.startsWith(CLASSPATH_ALL_URL_PREFIX)) {
        // a class path resource (multiple resources for same name possible)
        if (getPathMatcher().isPattern(locationPattern.substring(CLASSPATH_ALL_URL_PREFIX.length()))) {
        // a class path resource pattern
        return findPathMatchingResources(locationPattern);
        }
        else {
        // all class path resources with the given name
        return findAllClassPathResources(locationPattern.substring(CLASSPATH_ALL_URL_PREFIX.length()));
        }
        }
        else {
        // Only look for a pattern after a prefix here
        // (to not get fooled by a pattern symbol in a strange prefix).
        int prefixEnd = locationPattern.indexOf(":") + 1;
        if (getPathMatcher().isPattern(locationPattern.substring(prefixEnd))) {
        // a file pattern
        return findPathMatchingResources(locationPattern);
        }
        else {
        // a single resource with the given name
        return new Resource[] {getResourceLoader().getResource(locationPattern)};
        }
        }
        }
    ここで、上のclassipath*:パスと:先頭のパスの下のResourceが見つかりました.
  • BenDefinitionのロードと解析
  • 私たちはrefreshに戻ってきて、ロードを見に来ました.
        public void refresh() throws BeansException, IllegalStateException {
        synchronized (this.startupShutdownMonitor) {
        // Prepare this context for refreshing.
        prepareRefresh();
    
    
        // Tell the subclass to refresh the internal bean factory.
        ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
    
    
        // Prepare the bean factory for use in this context.
        prepareBeanFactory(beanFactory);
    
    
        try {
        // Allows post-processing of the bean factory in context subclasses.
        postProcessBeanFactory(beanFactory);
    
    
        // Invoke factory processors registered as beans in the context.
        invokeBeanFactoryPostProcessors(beanFactory);
    
    
        // Register bean processors that intercept bean creation.
        registerBeanPostProcessors(beanFactory);
    
    
        // Initialize message source for this context.
        initMessageSource();
    
    
        // Initialize event multicaster for this context.
        initApplicationEventMulticaster();
    
    
        // Initialize other special beans in specific context subclasses.
        onRefresh();
    
    
        // Check for listener beans and register them.
        registerListeners();
    
    
        // Instantiate all remaining (non-lazy-init) singletons.
        finishBeanFactoryInitialization(beanFactory);
    
    
        // Last step: publish corresponding event.
        finishRefresh();
        }
    
    
        catch (BeansException ex) {
        // Destroy already created singletons to avoid dangling resources.
        destroyBeans();
    
    
        // Reset 'active' flag.
        cancelRefresh(ex);
    
    
        // Propagate exception to caller.
        throw ex;
        }
        }
        }
    上の全体refresh方法はコンピュータシステムの再起動と同じである.私たちは簡単なバージョンのロードを見ます.Xml BenFactoryからの
        public XmlBeanFactory(Resource resource, BeanFactory parentBeanFactory) throws BeansException {
          super(parentBeanFactory);
          this.reader.loadBeanDefinitions(resource);
       }
    
    はXml BeanDefinitionReaderのに入ります.
        public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
              Assert.notNull(encodedResource, "EncodedResource must not be null");
              if (logger.isInfoEnabled()) {
                 logger.info("Loading XML bean definitions from " + encodedResource.getResource());
              }
    
    
              Set<EncodedResource> currentResources = this.resourcesCurrentlyBeingLoaded.get();
              if (currentResources == null) {
                 currentResources = new HashSet<EncodedResource>(4);
                 this.resourcesCurrentlyBeingLoaded.set(currentResources);
              }
              if (!currentResources.add(encodedResource)) {
                 throw new BeanDefinitionStoreException(
                       "Detected cyclic loading of " + encodedResource + " - check your import definitions!");
              }
              try {
                 InputStream inputStream = encodedResource.getResource().getInputStream();
                 try {
                    InputSource inputSource = new InputSource(inputStream);
                    if (encodedResource.getEncoding() != null) {
                       inputSource.setEncoding(encodedResource.getEncoding());
                    }
                    return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
                 }
                 finally {
                    inputStream.close();
                 }
              }
              catch (IOException ex) {
                    //....
              }
           }
    はまた入ります.
    protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
             throws BeanDefinitionStoreException {
          try {
             int validationMode = getValidationModeForResource(resource);
             Document doc = this.documentLoader.loadDocument(
                   inputSource, getEntityResolver(), this.errorHandler, validationMode, isNamespaceAware());
             return registerBeanDefinitions(doc, resource);
          }
          catch (BeanDefinitionStoreException ex) {
             //..
          }
          }
    
    
          public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
                  BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
                  documentReader.setEnvironment(this.getEnvironment());
                  int countBefore = getRegistry().getBeanDefinitionCount();
                  documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
                  return getRegistry().getBeanDefinitionCount() - countBefore;
            }
    上でXmlのプロファイルをメモリに読み込んでXml DcumentにしてBenDefinitionDcuntReaderに渡してこのDcumentを解析します.
    Default BeanDefinitionDcument Reader類に入ってみます.
    private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
          if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {
             importBeanDefinitionResource(ele);
          }
          else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {
             processAliasRegistration(ele);
          }
          else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
             processBeanDefinition(ele, delegate);
          }
          else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
             // recurse
             doRegisterBeanDefinitions(ele);
          }
       }
    これで、タグの解析が始まります.
  • BenDefinition登録