1. 程式人生 > >spring初始化refresh()方法中obtainFreshBeanFactory()原始碼走讀。

spring初始化refresh()方法中obtainFreshBeanFactory()原始碼走讀。

/**
* Tell the subclass to refresh the internal bean factory.
* @return the fresh BeanFactory instance
* @see #refreshBeanFactory()
* @see #getBeanFactory()
*/
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
refreshBeanFactory();----》點選進入
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
if
(logger.isDebugEnabled()) {
logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
}
return beanFactory;
}
----》進入org.springframework.context.support.AbstractRefreshableApplicationContext--refreshBeanFactory()方法
繼承關係圖
/** * This implementation performs an actual refresh of this context's underlying
* bean factory, shutting down the previous bean factory (if any) and
* initializing a fresh bean factory for the next phase of the context's lifecycle.
*/
@Override
protected final void refreshBeanFactory() throws BeansException {
  //檢查BeanFactory是否已經存在,存在的話銷燬
if (hasBeanFactory()) {
destroyBeans();

closeBeanFactory();
}
try {
DefaultListableBeanFactory beanFactory = createBeanFactory();//例項化DefaultListableBeanFactory
beanFactory.setSerializationId(getId());
customizeBeanFactory(beanFactory);
loadBeanDefinitions(beanFactory); //解析XML 裝載成BeanDefinition物件
--》點選進入
synchronized (this.beanFactoryMonitor) {
this.beanFactory = beanFactory;
}
}
catch (IOException ex) {
throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
}
}
===============================================================================
org.springframework.web.context.support.AbstractRefreshableApplicationContext.loadBeanDefinitions()方法 ---(抽象類AbstractRefreshableApplicationContext 分別被下面四個 類 實現
--》進入org.springframework.web.context.support.XmlWebApplicationContext--loadBeanDefinitions()方法
/**
* 通過XmlBeanDefinitionReader 載入和定義bean
* Loads the bean definitions via an XmlBeanDefinitionReader.
* @see org.springframework.beans.factory.xml.XmlBeanDefinitionReader
* @see #initBeanDefinitionReader
* @see #loadBeanDefinitions
*/
@Override
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
// Create a new XmlBeanDefinitionReader for the given BeanFactory.
XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);

// Configure the bean definition reader with this context's
// resource loading environment.
beanDefinitionReader.setEnvironment(getEnvironment()); //設定 StandardEnvironment
beanDefinitionReader.setResourceLoader(this);
beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));

// Allow a subclass to provide custom initialization of the reader,
// then proceed with actually loading the bean definitions.
initBeanDefinitionReader(beanDefinitionReader);
  //解析spring配置的XXXXapplication.xml 具體執行-AbstractBeanDefinitionReader.loadBeanDefinitions()
loadBeanDefinitions(beanDefinitionReader);
}
XmlWebApplicationContext
執行:org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions()方法
目的:將spring xxxxApplication.xml--轉化為Resource 可以理解為IO流資源
下面的 resourceLoader 就是 XmlWebApplicationContext上一步方法賦值的 XmlWebApplicationContext 

public int loadBeanDefinitions(String location, Set<Resource> actualResources) throws BeanDefinitionStoreException {
   ResourceLoader resourceLoader = getResourceLoader(); 
if (resourceLoader == null) {
throw new BeanDefinitionStoreException(
"Cannot import bean definitions from location [" + location + "]: no ResourceLoader available");
}

if (resourceLoader instanceof ResourcePatternResolver) {
// Resource pattern matching available.
try {
Resource[] resources = ((ResourcePatternResolver) resourceLoader).getResources(location);
int loadCount = loadBeanDefinitions(resources); //進入--這裡以XML解析為例
if (actualResources != null) {
for (Resource resource : resources) {
actualResources.add(resource);
}
}
if (logger.isDebugEnabled()) {
logger.debug("Loaded " + loadCount + " bean definitions from location pattern [" + location + "]");
}
return loadCount;
}
catch (IOException ex) {
throw new BeanDefinitionStoreException(
"Could not resolve bean definition resource pattern [" + location + "]", ex);
}
}
else {
// Can only load single resources by absolute URL.
Resource resource = resourceLoader.getResource(location);
int loadCount = loadBeanDefinitions(resource);
if (actualResources != null) {
actualResources.add(resource);
}
if (logger.isDebugEnabled()) {
logger.debug("Loaded " + loadCount + " bean definitions from location [" + location + "]");
}
return loadCount;
}
}

---》進入後 org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions()方法;主要作用 Resource--》EncodedResource(實現InputStreamSource)---》InputSource  IO流 
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());
        //上面的這條語句進入之後構造出 org.w3c.dom.Document doc = doLoadDocument(inputSource, resource);
//之後的工作就是利用java api提供的Document解析XML
      }
finally {
inputStream.close();
}
}
//各種不斷進入之後
org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader.parseDefaultElement()方法
private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
/**解析import 標籤的XML 例如: * <import resource="applicationContext-common.xml" /> * <import resource="applicationContext-datasource.xml" />* 進入importBeanDefinitionResource()--因為每個import引入一個xml spring 還是會向現在我們解析application.x *ml去解析一樣--裡面呼叫的方法 * int importCount = getReaderContext().getReader().loadBeanDefinitions(location, actualResources); * 執行的是org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions *( locatiom, actualResources)方法 ***/

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); //解析bean<bean id="" class="" /> --進入

}
else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
// recurse
doRegisterBeanDefinitions(ele);
}
}
----》檢視解析進入bean的具體實現方法 org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader.processBeanDefinition()方法
解析:BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
     1、對Element 屬性getAttribute("id"/"name")
     2、對獲得id/name 賦值給GenericBeanDefinition物件 它實現AbstractBeanDefinition-->BeanDefinition介面
AbstractBeanDefinition物件就是儲存解析的bean 屬性 並對預設屬性賦值 id/name/scope/lazyInit/beanClass/initMethodName/propertyValues......)
        方法:AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, conta              iningBean);
     3、構造返回 new BeanDefinitionHolder(beanDefinition,beanName,aliasesArray)  裡面就是beanName、
        aliasesArray、beanDefinition(物件) 方便後面spring 依賴注入直接通過beanName/aliasesArray(別名)        獲取beanDefinition物件。
   解析:BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry()
        1、獲取bdHolder的beanName和BeanDefinition 物件
        2、將BeanDefinitionRegistry----》registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
        3、將beanName 新增到List<String>,將beanName--key和beanDefinition--value 儲存到 Map<String, BeanDefinition> 中。