IOC容器的初始化是由refresh()方法來啓動的,這個方法標誌着IOC容器的正式啓動。
Resource定位過程:把容器比做水桶,類似於容器查找數據,提着水桶尋找水源;
BeanDefinition載入:容器中的主要的數據結構,類似於水;
**向IOC容器中註冊這些BeanDefinition:**把水倒入水桶中;
在這個註冊的過程中,一般不包含Bean依賴注入的實現。在SpringIOC設計過程中,載入和依賴注入是兩個過程。依賴注入發生在第一次獲取bean的時候。
BeanDefinition的Resource定位
ClassPathResource res = new ClassPathResource(“beans.xml”);
org.springframework.context.support.AbstractRefreshableApplicationContext#refreshBeanFactory
protected final void refreshBeanFactory() throws BeansException {
//在這裏進行判斷,如果已經有了beanFactory,則銷燬並關閉
if (this.hasBeanFactory()) {
this.destroyBeans();
this.closeBeanFactory();
}
try {
//創建DefaultListableBeanFactory
DefaultListableBeanFactory beanFactory = this.createBeanFactory();
beanFactory.setSerializationId(this.getId());
this.customizeBeanFactory(beanFactory);
//調用loadBeanDefinitions再載入BeanDefinition信息
this.loadBeanDefinitions(beanFactory);
synchronized(this.beanFactoryMonitor) {
this.beanFactory = beanFactory;
}
} catch (IOException var5) {
throw new ApplicationContextException("I/O error parsing bean definition source for " + this.getDisplayName(), var5);
}
}
org.springframework.core.io.DefaultResourceLoader#getResource
public Resource getResource(String location) {
Assert.notNull(location, "Location must not be null");
//這裏處理classpath:開頭的路徑
if (location.startsWith("classpath:")) {
return new ClassPathResource(location.substring("classpath:".length()), this.getClassLoader());
} else {
try {
//這裏處理URL表示的Resource位置
URL url = new URL(location);
return new UrlResource(url);
} catch (MalformedURLException var3) {
//如果兩個都不是,則通過下面的方法獲取
return this.getResourceByPath(location);
}
}
}
org.springframework.context.support.FileSystemXmlApplicationContext#FileSystemXmlApplicationContext(java.lang.String[], boolean, org.springframework.context.ApplicationContext)
public FileSystemXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent) throws BeansException {
super(parent);
this.setConfigLocations(configLocations);
//這裏調用容器的refresh,是載入BeanDefinition的入口
if (refresh) {
this.refresh();
}
}
BeanDefinition的載入和解析
org.springframework.context.support.AbstractApplicationContext#refresh
public void refresh() throws BeansException, IllegalStateException {
synchronized(this.startupShutdownMonitor) {
this.prepareRefresh();
//這裏是在子類中啓動refreshBeanFactory的地方
ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();
//準備在這個上下文環境中使用的BeanFactory
this.prepareBeanFactory(beanFactory);
try {
//設置BeanFactory的後置處理器
this.postProcessBeanFactory(beanFactory);
//調用BeanFactory的後置處理器,這些後處理器是在Bean定義中向容器註冊的
this.invokeBeanFactoryPostProcessors(beanFactory);
//註冊Bean的後處理器,在Bean創建過程中調用;
this.registerBeanPostProcessors(beanFactory);
//對上下文中的消息源進行初始化
this.initMessageSource();
//初始化上下文中的事件機制
this.initApplicationEventMulticaster();
//初始化其他特殊的Bean
this.onRefresh();
//檢查監聽Bean並且將這些Bean向容器註冊
this.registerListeners();
//實例化所有的non-lazy-inti單件
this.finishBeanFactoryInitialization(beanFactory);
//發佈容器事件,結束Refresh過程
this.finishRefresh();
} catch (BeansException var5) {
//爲防止Bean資源佔用,在異常處理中,銷燬已經生成的bean
this.logger.warn("Exception encountered during context initialization - cancelling refresh attempt", var5);
this.destroyBeans();
//重置active標誌
this.cancelRefresh(var5);
throw var5;
}
}
}
org.springframework.beans.factory.xml.XmlBeanDefinitionReader#loadBeanDefinitions(org.springframework.core.io.support.EncodedResource)
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
//創建beanDefinitionReader,並且通過回調設置到BeanFactory中
XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
beanDefinitionReader.setEnvironment(this.getEnvironment());
//beanDefinitionReader配置ResourceLoader,因爲DefaultResourceLoader是父類,可以直接使用this
beanDefinitionReader.setResourceLoader(this);
beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));
//這裏啓動bean定義信息載入過程
this.initBeanDefinitionReader(beanDefinitionReader);
this.loadBeanDefinitions(beanDefinitionReader);
}
org.springframework.context.support.AbstractXmlApplicationContext#loadBeanDefinitions(org.springframework.beans.factory.xml.XmlBeanDefinitionReader)
protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
//以Resource形式獲取配置文件的資源位置
Resource[] configResources = this.getConfigResources();
if (configResources != null) {
reader.loadBeanDefinitions(configResources);
}
//以String數組的形式獲取配置文件的資源位置
String[] configLocations = this.getConfigLocations();
if (configLocations != null) {
reader.loadBeanDefinitions(configLocations);
}
}
org.springframework.beans.factory.support.AbstractBeanDefinitionReader#loadBeanDefinitions(org.springframework.core.io.Resource…)
public int loadBeanDefinitions(Resource… resources) throws BeanDefinitionStoreException {
Assert.notNull(resources, "Resource array must not be null");
int counter = 0;
Resource[] arr$ = resources;
int len$ = resources.length;
//遍歷Resource中包含的BeanDefinition信息
for(int i$ = 0; i$ < len$; ++i$) {
Resource resource = arr$[i$];
counter += this.loadBeanDefinitions((Resource)resource);
}
return counter;
}
org.springframework.beans.factory.xml.XmlBeanDefinitionReader#loadBeanDefinitions(org.springframework.core.io.support.EncodedResource)
//這裏載入XML形式的BeanDefinition的地方
public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
Assert.notNull(encodedResource, "EncodedResource must not be null");
if (this.logger.isInfoEnabled()) {
this.logger.info("Loading XML bean definitions from " + encodedResource.getResource());
}
Set<EncodedResource> currentResources = (Set)this.resourcesCurrentlyBeingLoaded.get();
if (currentResources == null) {
currentResources = new HashSet(4);
this.resourcesCurrentlyBeingLoaded.set(currentResources);
}
if (!((Set)currentResources).add(encodedResource)) {
throw new BeanDefinitionStoreException("Detected cyclic loading of " + encodedResource + " - check your import definitions!");
} else {
int var5;
//這裏得到XML文件,並得到IO的INPUTSOURCE準備進行讀取
try {
InputStream inputStream = encodedResource.getResource().getInputStream();
try {
InputSource inputSource = new InputSource(inputStream);
if (encodedResource.getEncoding() != null) {
inputSource.setEncoding(encodedResource.getEncoding());
}
var5 = this.doLoadBeanDefinitions(inputSource, encodedResource.getResource());
} finally {
inputStream.close();
}
} catch (IOException var15) {
throw new BeanDefinitionStoreException("IOException parsing XML document from " + encodedResource.getResource(), var15);
} finally {
((Set)currentResources).remove(encodedResource);
if (((Set)currentResources).isEmpty()) {
this.resourcesCurrentlyBeingLoaded.remove();
}
}
return var5;
}
}
BeanDefinition在IOC容器中的註冊
org.springframework.beans.factory.xml.XmlBeanDefinitionReader#doLoadBeanDefinitions
protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource) throws BeanDefinitionStoreException {
try {
int validationMode = this.getValidationModeForResource(resource);
//這裏取得XML文件的DOC對象,這個解析過程是由Document完成的。
Document doc = this.documentLoader.loadDocument(inputSource, this.getEntityResolver(), this.errorHandler, validationMode, this.isNamespaceAware());
//這裏啓動的是對BeanDefinition解析的詳細過程,這個解析會使用到spring的Bean配置規則
return this.registerBeanDefinitions(doc, resource);
} catch (BeanDefinitionStoreException var5) {
throw var5;
} catch (SAXParseException var6) {
throw new XmlBeanDefinitionStoreException(resource.getDescription(), "Line " + var6.getLineNumber() + " in XML document from " + resource + " is invalid", var6);
} catch (SAXException var7) {
throw new XmlBeanDefinitionStoreException(resource.getDescription(), "XML document from " + resource + " is invalid", var7);
} catch (ParserConfigurationException var8) {
throw new BeanDefinitionStoreException(resource.getDescription(), "Parser configuration exception parsing XML from " + resource, var8);
} catch (IOException var9) {
throw new BeanDefinitionStoreException(resource.getDescription(), "IOException parsing XML document from " + resource, var9);
} catch (Throwable var10) {
throw new BeanDefinitionStoreException(resource.getDescription(), "Unexpected exception parsing XML document from " + resource, var10);
}
}
org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader#processBeanDefinition
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
//BeanDefinitionHolder是BeanDefinition的封裝類,封裝了BeanDefinition、Bean的名字和別名,用它來向IOC容器註冊;
//得到BeanDefinitionHolder表明通過了sping規則解析得到的
BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
if (bdHolder != null) {
bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
try {
//這裏是向IOC容器註冊解析得到的BeanDefinition的地方
BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, this.getReaderContext().getRegistry());
} catch (BeanDefinitionStoreException var5) {
this.getReaderContext().error("Failed to register bean definition with name '" + bdHolder.getBeanName() + "'", ele, var5);
}
//在BeanDefinition向ICO容器註冊後,發送消息
this.getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
}
}
org.springframework.beans.factory.xml.BeanDefinitionParserDelegate#parseBeanDefinitionElement(org.w3c.dom.Element, org.springframework.beans.factory.config.BeanDefinition)
public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, BeanDefinition containingBean) {
//這裏獲取<bean>元素定義的id、name和aliase屬性的值
String id = ele.getAttribute("id");
String nameAttr = ele.getAttribute("name");
List<String> aliases = new ArrayList();
if (StringUtils.hasLength(nameAttr)) {
String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, ",; ");
aliases.addAll(Arrays.asList(nameArr));
}
String beanName = id;
if (!StringUtils.hasText(id) && !aliases.isEmpty()) {
beanName = (String)aliases.remove(0);
if (this.logger.isDebugEnabled()) {
this.logger.debug("No XML 'id' specified - using '" + beanName + "' as bean name and " + aliases + " as aliases");
}
}
if (containingBean == null) {
this.checkNameUniqueness(beanName, aliases, ele);
}
//這個方法是對Bean的詳細解析
AbstractBeanDefinition beanDefinition = this.parseBeanDefinitionElement(ele, beanName, containingBean);
if (beanDefinition != null) {
if (!StringUtils.hasText(beanName)) {
try {
if (containingBean != null) {
beanName = BeanDefinitionReaderUtils.generateBeanName(beanDefinition, this.readerContext.getRegistry(), true);
} else {
beanName = this.readerContext.generateBeanName(beanDefinition);
String beanClassName = beanDefinition.getBeanClassName();
if (beanClassName != null && beanName.startsWith(beanClassName) && beanName.length() > beanClassName.length() && !this.readerContext.getRegistry().isBeanNameInUse(beanClassName)) {
aliases.add(beanClassName);
}
}
if (this.logger.isDebugEnabled()) {
this.logger.debug("Neither XML 'id' nor 'name' specified - using generated bean name [" + beanName + "]");
}
} catch (Exception var9) {
this.error(var9.getMessage(), ele);
return null;
}
}
String[] aliasesArray = StringUtils.toStringArray(aliases);
return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray);
} else {
return null;
}
}
org.springframework.beans.factory.xml.BeanDefinitionParserDelegate#parseBeanDefinitionElement(org.w3c.dom.Element, java.lang.String, org.springframework.beans.factory.config.BeanDefinition)
public AbstractBeanDefinition parseBeanDefinitionElement(Element ele, String beanName, BeanDefinition containingBean) {
this.parseState.push(new BeanEntry(beanName));
//這是隻是獲取bean定義中的class名字,然後載入在BeanDefinition中,只是記錄,不涉及實例化過程,實例化是依賴注入時進行的
String className = null;
if (ele.hasAttribute("class")) {
className = ele.getAttribute("class").trim();
}
try {
String parent = null;
if (ele.hasAttribute("parent")) {
parent = ele.getAttribute("parent");
}
//這裏生成需要的BeanDefinition對象,爲Bean定義信息的載入做準備
AbstractBeanDefinition bd = this.createBeanDefinition(className, parent);
//這裏對當前的bean元素進行屬性解析,並設置describe信息
this.parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);
bd.setDescription(DomUtils.getChildElementValueByTagName(ele, "description"));
//這裏是對bean元素的信息進行解析的地方
this.parseMetaElements(ele, bd);
this.parseLookupOverrideSubElements(ele, bd.getMethodOverrides());
this.parseReplacedMethodSubElements(ele, bd.getMethodOverrides());
//解析bean的構造函數設置
this.parseConstructorArgElements(ele, bd);
//解析bean的property設置
this.parsePropertyElements(ele, bd);
this.parseQualifierElements(ele, bd);
bd.setResource(this.readerContext.getResource());
bd.setSource(this.extractSource(ele));
AbstractBeanDefinition var7 = bd;
return var7;
//經常看到的異常信息
} catch (ClassNotFoundException var13) {
this.error("Bean class [" + className + "] not found", ele, var13);
} catch (NoClassDefFoundError var14) {
this.error("Class that bean class [" + className + "] depends on not found", ele, var14);
} catch (Throwable var15) {
this.error("Unexpected failure during bean definition parsing", ele, var15);
} finally {
this.parseState.pop();
}
return null;
}