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()
- 載入NameSpacehandler
- 使用各個NameSpcaceHandler生成Beandifinitions並註冊到beanfactory裡面去
3.2.1 載入NameSpaceHandler
NameSpaceHandler
載入過程的解析已經寫過就不再寫了; 參看前面的文章
3.2.2 NameSpaceHandler處理生成bean的定義(注意只是生成beanDefinition而不是生成具體的bean而且相關的Class檔案也沒有載入)
- NamespaceHandlerSupport
//返回也沒用,應該定義為void的,parserContext的registry就是beanFactory public BeanDefinition parse(Element element, ParserContext parserContext) { //獲取具體的BeanDefinitionParser,比如說ComponentScanBeanDefinitionParser return findParserForElement(element, parserContext).parse(element, parserContext); }
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的各種載入邏輯了...