1. 程式人生 > >SpringBeanContainer的啟動載入初始化流程

SpringBeanContainer的啟動載入初始化流程

1. DESC

Spring對beanFactory的處理

2. CODE

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) {
            if (logger.isWarnEnabled()) {
                logger.warn("Exception encountered during context initialization-cancelling refresh attempt: " + ex);
            }
            // Destroy already created singletons to avoid dangling resources.
            destroyBeans();
            // Reset 'active' flag.
            cancelRefresh(ex);
            // Propagate exception to caller.
            throw ex;
        }finally {
            // Reset common introspection caches in Spring's core, since we
            // might not ever need metadata for singleton beans anymore...
            resetCommonCaches();
        }
    }
}

3. 從上往下RUSH

3.1 prepareRefresh()

這裡不用細看就是自身進行些配置和引數校驗什麼的

3.2 obtainFreshBeanFactory()

  1. 載入NameSpacehandler
  2. 使用各個NameSpcaceHandler生成Beandifinitions並註冊到beanfactory裡面去

3.2.1 載入NameSpaceHandler

  1. NameSpaceHandler載入過程的解析已經寫過就不再寫了; 參看前面的文章

3.2.2 NameSpaceHandler處理生成bean的定義(注意只是生成beanDefinition而不是生成具體的bean而且相關的Class檔案也沒有載入)

  1. NamespaceHandlerSupport
//返回也沒用,應該定義為void的,parserContext的registry就是beanFactory
public BeanDefinition parse(Element element, ParserContext parserContext) {
    //獲取具體的BeanDefinitionParser,比如說ComponentScanBeanDefinitionParser
    return findParserForElement(element, parserContext).parse(element, parserContext);
}
  1. ComponentScanBeanDefinitionParser 這是個樣板例子,一看就知道怎麼回事
public BeanDefinition parse(Element element, ParserContext parserContext) {
    String basePackage = element.getAttribute(BASE_PACKAGE_ATTRIBUTE);//獲取basepackage設定的包名
    basePackage = parserContext.getReaderContext().getEnvironment().resolvePlaceholders(basePackage);//有可能使用了$
    String[] basePackages = StringUtils.tokenizeToStringArray(basePackage,ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS);//解析出全部的package
    // Actually scan for bean definitions and register them.
    ClassPathBeanDefinitionScanner scanner = configureScanner(parserContext, element);//配置掃描器
    Set<BeanDefinitionHolder> beanDefinitions = scanner.doScan(basePackages);//掃包
    registerComponents(parserContext.getReaderContext(), beanDefinitions, element);//向beanFactory註冊
    return null;
}

3.3 prepareBeanFactory(beanFactory)

主要是完成BeanFactoryPostProcessors的初始化

protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
	...
	 //注意這是LTW,載入時程式碼織入進行增強AOP
	if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
		beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
	}
	...
}

3.4 invokeBeanFactoryPostProcessors(beanFactory) 執行BeanFactoryPostProcessors,

對BeanFactory啟動處理流程

protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
	PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors()); //需要注意的有個AspectJWeavingEnabler比較特殊,這個類的目的在於啟用ClassLoader級別的Aop,和以前的Instrument In Jvm 有點類似,
	// 檢測是否有LTW支援,
	if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
		beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
		beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
	}
}

3.5 後面的幾個方法感覺不用寫了

就是bean的初始化什麼的了;

其實想抓下Transactional的實現程式碼的;(這個有點不太明白和JVM redifineClass是怎麼對活動棧幀進行方法棧的替換)

但我對AspectJ實在不熟,先放棄吧.等我點了ApsectJ的科技樹再回來補充;

4. 總結整體流程

ContextLoaderListener 初始化

new DefaultListableBeanFactory() 建立beanFactroy

new XmlBeanDefinitionReader(beanFactory) 建立解析器

new BeanDefinitionDocumentReader

載入配置檔案applicationContext.xml

根據 配置檔案內的tag的namespace 及 lib下所有jar的/META-INF/spring.handlers 確定NamespaceHandler 並對其初始化

根據 tag的具體值確定BeanDefinitionParser();呼叫parser.parse(Element element, ParserContext parserContext) 完成BeanDefinition的註冊,parserContext的registry 就是最開始建立的beanFactory;

postProcessBeanFactory()完成各種beanFatoryPostProcessor的初始化

執行這些完成各種beanFatoryPostProcessor 注意裡面有個比較特殊屬的AspectJWeavingEnabler 是負責啟用ClassLoader級別Aop的核心邏輯(就是在ClassLoader上注入ClassFileTransformer)

後面就是bean的各種載入邏輯了...