IOC源碼解析
IOC初始化
對(duì)于spring我們最熟悉的莫過(guò)于ApplicationContext這一接口了,首先回顧一下spring的使用流程
ApplicationContext context = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
上述代碼獲得了一個(gè)ApplicationContext容器,但是spring中的bean是如何注入到容器中去的呢?
這里從構(gòu)造函數(shù)開始入手
public ClassPathXmlApplicationContext(
String[] configLocations, boolean refresh, @Nullable ApplicationContext parent)
throws BeansException {
super(parent);
//解析Bean定義資源文件的路徑,處理多個(gè)資源文件字符串?dāng)?shù)組
setConfigLocations(configLocations);
if (refresh) {
//入口方法
refresh();
}
}
從構(gòu)造函數(shù)可以看出IOC的入口就是refresh方法,該方法在AbstractApplicationContext中
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// Prepare this context for refreshing.
//1、調(diào)用容器準(zhǔn)備刷新的方法,獲取容器的當(dāng)時(shí)時(shí)間,同時(shí)給容器設(shè)置同步標(biāo)識(shí)
prepareRefresh();
// Tell the subclass to refresh the internal bean factory.
//2、告訴子類啟動(dòng)refreshBeanFactory()方法,Bean定義資源文件的載入從
//子類的refreshBeanFactory()方法啟動(dòng)
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// Prepare the bean factory for use in this context.
//3、為BeanFactory配置容器特性,例如類加載器、事件處理器等
prepareBeanFactory(beanFactory);
try {
// Allows post-processing of the bean factory in context subclasses.
//4、為容器的某些子類指定特殊的BeanPost事件處理器
postProcessBeanFactory(beanFactory);
// Invoke factory processors registered as beans in the context.
//5、調(diào)用所有注冊(cè)的BeanFactoryPostProcessor的Bean
invokeBeanFactoryPostProcessors(beanFactory);
// Register bean processors that intercept bean creation.
//6、為BeanFactory注冊(cè)BeanPost事件處理器.
//BeanPostProcessor是Bean后置處理器,用于監(jiān)聽容器觸發(fā)的事件
registerBeanPostProcessors(beanFactory);
// Initialize message source for this context.
//7、初始化信息源,和國(guó)際化相關(guān).
initMessageSource();
// Initialize event multicaster for this context.
//8、初始化容器事件傳播器.
initApplicationEventMulticaster();
// Initialize other special beans in specific context subclasses.
//9、調(diào)用子類的某些特殊Bean初始化方法
onRefresh();
// Check for listener beans and register them.
//10、為事件傳播器注冊(cè)事件監(jiān)聽器.
registerListeners();
// Instantiate all remaining (non-lazy-init) singletons.
//11、初始化所有剩余的單例Bean
finishBeanFactoryInitialization(beanFactory);
// Last step: publish corresponding event.
//12、初始化容器的生命周期事件處理器,并發(fā)布容器的生命周期事件
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.
//13、銷毀已創(chuàng)建的Bean
destroyBeans();
// Reset 'active' flag.
//14、取消refresh操作,重置容器的同步標(biāo)識(shí)。
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...
//15、重設(shè)公共緩存
resetCommonCaches();
}
}
}
這里可以看出obtainFreshBeanFactory方法獲得了一個(gè)BeanFactory容器
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
//這里使用了委派設(shè)計(jì)模式,父類定義了抽象的refreshBeanFactory()方法,具體實(shí)現(xiàn)調(diào)用子類容器的refreshBeanFactory()方法
refreshBeanFactory();
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
if (logger.isDebugEnabled()) {
logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
}
return beanFactory;
}
這里調(diào)用了refreshBeanFactory方法這是一個(gè)抽象方法,具體邏輯由子類實(shí)現(xiàn)
這里進(jìn)入AbstractRefreshableApplicationContext中的refreshBeanFactory方法
protected final void refreshBeanFactory() throws BeansException {
//如果已經(jīng)有容器,銷毀容器中的bean,關(guān)閉容器
if (hasBeanFactory()) {
destroyBeans();
closeBeanFactory();
}
try {
//創(chuàng)建IOC容器
DefaultListableBeanFactory beanFactory = createBeanFactory();
beanFactory.setSerializationId(getId());
//對(duì)IOC容器進(jìn)行定制化,如設(shè)置啟動(dòng)參數(shù),開啟注解的自動(dòng)裝配等(這里解析了是否允許循環(huán)引用)
customizeBeanFactory(beanFactory);
//調(diào)用載入Bean定義的方法,主要這里又使用了一個(gè)委派模式,在當(dāng)前類中只定義了抽象的loadBeanDefinitions方法,具體的實(shí)現(xiàn)調(diào)用子類容器
loadBeanDefinitions(beanFactory);
synchronized (this.beanFactoryMonitor) {
this.beanFactory = beanFactory;
}
}
catch (IOException ex) {
throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
}
}
這里調(diào)用loadBeanDefinitions方法解析BeanDefinition,他是一個(gè)抽象方法同時(shí)是由子類實(shí)現(xiàn)
其中AbstractRefreshableApplicationContext主要有四個(gè)實(shí)現(xiàn)
AbstractXmlApplicationContext 解析xml
AnnotationConfigWebApplicationContext 解析注解
GroovyWebApplicationContext 適配groovy
XmlWebApplicationContext web環(huán)境
這里進(jìn)入AbstractXmlApplicationContext的loadBeanDefinitions
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
// Create a new XmlBeanDefinitionReader for the given BeanFactory.
//創(chuàng)建XmlBeanDefinitionReader,即創(chuàng)建Bean讀取器,并通過(guò)回調(diào)設(shè)置到容器中去,容器使用該讀取器讀取Bean定義資源
XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
// Configure the bean definition reader with this context's
// resource loading environment.
//為Bean讀取器設(shè)置Spring資源加載器,AbstractXmlApplicationContext的
//祖先父類AbstractApplicationContext繼承DefaultResourceLoader,因此,容器本身也是一個(gè)資源加載器
beanDefinitionReader.setEnvironment(this.getEnvironment());
beanDefinitionReader.setResourceLoader(this);
//為Bean讀取器設(shè)置SAX xml解析器
beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));
// Allow a subclass to provide custom initialization of the reader,
// then proceed with actually loading the bean definitions.
//當(dāng)Bean讀取器讀取Bean定義的Xml資源文件時(shí),啟用Xml的校驗(yàn)機(jī)制
initBeanDefinitionReader(beanDefinitionReader);
//Bean讀取器真正實(shí)現(xiàn)加載的方法
loadBeanDefinitions(beanDefinitionReader);
}
這里使用beanDefinitionReader類解析,最終使用loadBeanDefinitions方法去加載
protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
//獲取Bean定義資源的定位
Resource[] configResources = getConfigResources();
if (configResources != null) {
//Xml Bean讀取器調(diào)用其父類AbstractBeanDefinitionReader讀取定位
//的Bean定義資源
reader.loadBeanDefinitions(configResources);
}
//如果子類中獲取的Bean定義資源定位為空,則獲取FileSystemXmlApplicationContext構(gòu)造方法中setConfigLocations方法設(shè)置的資源
String[] configLocations = getConfigLocations();
if (configLocations != null) {
//Xml Bean讀取器調(diào)用其父類AbstractBeanDefinitionReader讀取定位
//的Bean定義資源
reader.loadBeanDefinitions(configLocations);
}
}
追蹤loadBeanDefinitions方法最終執(zhí)行到XmlBeanDefinitionReader中的doLoadBeanDefinitions方法
protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
throws BeanDefinitionStoreException {
try {
//將XML文件轉(zhuǎn)換為DOM對(duì)象,解析過(guò)程由documentLoader實(shí)現(xiàn)
Document doc = doLoadDocument(inputSource, resource);
//這里是啟動(dòng)對(duì)Bean定義解析的詳細(xì)過(guò)程,該解析過(guò)程會(huì)用到Spring的Bean配置規(guī)則
return registerBeanDefinitions(doc, resource);
}
catch (BeanDefinitionStoreException ex) {
throw ex;
}
catch (SAXParseException ex) {
throw new XmlBeanDefinitionStoreException(resource.getDescription(),
"Line " + ex.getLineNumber() + " in XML document from " + resource + " is invalid", ex);
}
catch (SAXException ex) {
throw new XmlBeanDefinitionStoreException(resource.getDescription(),
"XML document from " + resource + " is invalid", ex);
}
catch (ParserConfigurationException ex) {
throw new BeanDefinitionStoreException(resource.getDescription(),
"Parser configuration exception parsing XML from " + resource, ex);
}
catch (IOException ex) {
throw new BeanDefinitionStoreException(resource.getDescription(),
"IOException parsing XML document from " + resource, ex);
}
catch (Throwable ex) {
throw new BeanDefinitionStoreException(resource.getDescription(),
"Unexpected exception parsing XML document from " + resource, ex);
}
}
最終調(diào)用DefaultBeanDefinitionDocumentReader中的doRegisterBeanDefinitions方法
protected void doRegisterBeanDefinitions(Element root) {
// Any nested <beans> elements will cause recursion in this method. In
// order to propagate and preserve <beans> default-* attributes correctly,
// keep track of the current (parent) delegate, which may be null. Create
// the new (child) delegate with a reference to the parent for fallback purposes,
// then ultimately reset this.delegate back to its original (parent) reference.
// this behavior emulates a stack of delegates without actually necessitating one.
//具體的解析過(guò)程由BeanDefinitionParserDelegate實(shí)現(xiàn),
//BeanDefinitionParserDelegate中定義了Spring Bean定義XML文件的各種元素
BeanDefinitionParserDelegate parent = this.delegate;
this.delegate = createDelegate(getReaderContext(), root, parent);
if (this.delegate.isDefaultNamespace(root)) {
String profileSpec = root.getAttribute(PROFILE_ATTRIBUTE);
if (StringUtils.hasText(profileSpec)) {
String[] specifiedProfiles = StringUtils.tokenizeToStringArray(
profileSpec, BeanDefinitionParserDelegate.MULTI_VALUE_ATTRIBUTE_DELIMITERS);
if (!getReaderContext().getEnvironment().acceptsProfiles(specifiedProfiles)) {
if (logger.isInfoEnabled()) {
logger.info("Skipped XML bean definition file due to specified profiles [" + profileSpec +
"] not matching: " + getReaderContext().getResource());
}
return;
}
}
}
//在解析Bean定義之前,進(jìn)行自定義的解析,增強(qiáng)解析過(guò)程的可擴(kuò)展性
preProcessXml(root);
//從Document的根元素開始進(jìn)行Bean定義的Document對(duì)象
parseBeanDefinitions(root, this.delegate);
//在解析Bean定義之后,進(jìn)行自定義的解析,增加解析過(guò)程的可擴(kuò)展性
postProcessXml(root);
this.delegate = parent;
}
preProcessXml,postProcessXml是兩個(gè)擴(kuò)展方法,由用戶自己實(shí)現(xiàn),用來(lái)對(duì)Bean解析的前后加入自定義解析邏輯
parseBeanDefinitions方法開始從根元素解析Bean
protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
//Bean定義的Document對(duì)象使用了Spring默認(rèn)的XML命名空間
if (delegate.isDefaultNamespace(root)) {
//獲取Bean定義的Document對(duì)象根元素的所有子節(jié)點(diǎn)
NodeList nl = root.getChildNodes();
for (int i = 0; i < nl.getLength(); i++) {
Node node = nl.item(i);
//獲得Document節(jié)點(diǎn)是XML元素節(jié)點(diǎn)
if (node instanceof Element) {
Element ele = (Element) node;
//Bean定義的Document的元素節(jié)點(diǎn)使用的是Spring默認(rèn)的XML命名空間
if (delegate.isDefaultNamespace(ele)) {
//使用Spring的Bean規(guī)則解析元素節(jié)點(diǎn)
parseDefaultElement(ele, delegate);
}
else {
//沒有使用Spring默認(rèn)的XML命名空間,則使用用戶自定義的解//析規(guī)則解析元素節(jié)點(diǎn)
delegate.parseCustomElement(ele);
}
}
}
}
else {
//Document的根節(jié)點(diǎn)沒有使用Spring默認(rèn)的命名空間,則使用用戶自定義的
//解析規(guī)則解析Document根節(jié)點(diǎn)
delegate.parseCustomElement(root);
}
}
parseDefaultElement方法
////使用Spring的Bean規(guī)則解析Document元素節(jié)點(diǎn)
private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
//如果元素節(jié)點(diǎn)是<Import>導(dǎo)入元素,進(jìn)行導(dǎo)入解析
if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {
importBeanDefinitionResource(ele);
}
//如果元素節(jié)點(diǎn)是<Alias>別名元素,進(jìn)行別名解析
else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {
processAliasRegistration(ele);
}
//元素節(jié)點(diǎn)既不是導(dǎo)入元素,也不是別名元素,即普通的<Bean>元素,
//按照Spring的Bean規(guī)則解析元素
else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
processBeanDefinition(ele, delegate);
}
else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
// recurse
doRegisterBeanDefinitions(ele);
}
}
parseCustomElement方法
//用戶自定義解析規(guī)則
public BeanDefinition parseCustomElement(Element ele, @Nullable BeanDefinition containingBd) {
String namespaceUri = getNamespaceURI(ele);
if (namespaceUri == null) {
return null;
}
NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);
if (handler == null) {
error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", ele);
return null;
}
return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd));
}
importBeanDefinitionResource,processAliasRegistration自行觀看,這里列出processBeanDefinition方法
//解析Bean定義資源Document對(duì)象的普通元素
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
// BeanDefinitionHolder是對(duì)BeanDefinition的封裝,即Bean定義的封裝類
//對(duì)Document對(duì)象中<Bean>元素的解析由BeanDefinitionParserDelegate實(shí)現(xiàn)
// BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
if (bdHolder != null) {
bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
try {
// Register the final decorated instance.
//向Spring IOC容器注冊(cè)解析得到的Bean定義,這是Bean定義向IOC容器注冊(cè)的入口
BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
}
catch (BeanDefinitionStoreException ex) {
getReaderContext().error("Failed to register bean definition with name '" +
bdHolder.getBeanName() + "'", ele, ex);
}
// Send registration event.
//在完成向Spring IOC容器注冊(cè)解析得到的Bean定義之后,發(fā)送注冊(cè)事件
getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
}
}
在BeanDefinitionParserDelegate類下parseBeanDefinitionElement解析成BeanDefinitionHolder
//解析Bean定義資源文件中的<Bean>元素,這個(gè)方法中主要處理<Bean>元素的id,name和別名屬性
@Nullable
public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, @Nullable BeanDefinition containingBean) {
//獲取<Bean>元素中的id屬性值
String id = ele.getAttribute(ID_ATTRIBUTE);
//獲取<Bean>元素中的name屬性值
String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);
//獲取<Bean>元素中的alias屬性值
List<String> aliases = new ArrayList<>();
//將<Bean>元素中的所有name屬性值存放到別名中
if (StringUtils.hasLength(nameAttr)) {
String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, MULTI_VALUE_ATTRIBUTE_DELIMITERS);
aliases.addAll(Arrays.asList(nameArr));
}
String beanName = id;
//如果<Bean>元素中沒有配置id屬性時(shí),將別名中的第一個(gè)值賦值給beanName
if (!StringUtils.hasText(beanName) && !aliases.isEmpty()) {
beanName = aliases.remove(0);
if (logger.isDebugEnabled()) {
logger.debug("No XML 'id' specified - using '" + beanName +
"' as bean name and " + aliases + " as aliases");
}
}
//檢查<Bean>元素所配置的id或者name的唯一性,containingBean標(biāo)識(shí)<Bean>
//元素中是否包含子<Bean>元素
if (containingBean == null) {
//檢查<Bean>元素所配置的id、name或者別名是否重復(fù)
checkNameUniqueness(beanName, aliases, ele);
}
//詳細(xì)對(duì)<Bean>元素中配置的Bean定義進(jìn)行解析的地方
AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean);
if (beanDefinition != null) {
if (!StringUtils.hasText(beanName)) {
try {
if (containingBean != null) {
//如果<Bean>元素中沒有配置id、別名或者name,且沒有包含子元素
//<Bean>元素,為解析的Bean生成一個(gè)唯一beanName并注冊(cè)
beanName = BeanDefinitionReaderUtils.generateBeanName(
beanDefinition, this.readerContext.getRegistry(), true);
}
else {
//如果<Bean>元素中沒有配置id、別名或者name,且包含了子元素
//<Bean>元素,為解析的Bean使用別名向IOC容器注冊(cè)
beanName = this.readerContext.generateBeanName(beanDefinition);
// Register an alias for the plain bean class name, if still possible,
// if the generator returned the class name plus a suffix.
// This is expected for Spring 1.2/2.0 backwards compatibility.
//為解析的Bean使用別名注冊(cè)時(shí),為了向后兼容
//Spring1.2/2.0,給別名添加類名后綴
String beanClassName = beanDefinition.getBeanClassName();
if (beanClassName != null &&
beanName.startsWith(beanClassName) && beanName.length() > beanClassName.length() &&
!this.readerContext.getRegistry().isBeanNameInUse(beanClassName)) {
aliases.add(beanClassName);
}
}
if (logger.isDebugEnabled()) {
logger.debug("Neither XML 'id' nor 'name' specified - " +
"using generated bean name [" + beanName + "]");
}
}
catch (Exception ex) {
error(ex.getMessage(), ele);
return null;
}
}
String[] aliasesArray = StringUtils.toStringArray(aliases);
return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray);
}
//當(dāng)解析出錯(cuò)時(shí),返回null
return null;
}
解析完成之后調(diào)用BeanDefinitionReaderUtils中的registerBeanDefinition方法進(jìn)行注冊(cè)
最終調(diào)用DefaultListableBeanFactory中的registerBeanDefinition方法,將BeanDefinition信息放到beanDefinitionMap容器中
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);
registerBeanDefinition方法
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
throws BeanDefinitionStoreException {
//...
//校驗(yàn)解析的BeanDefiniton
if (beanDefinition instanceof AbstractBeanDefinition) {
try {
((AbstractBeanDefinition) beanDefinition).validate();
}
catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
"Validation of bean definition failed", ex);
}
}
BeanDefinition oldBeanDefinition;
//從容器中拿到BeanDefinition
oldBeanDefinition = this.beanDefinitionMap.get(beanName);
//如果容器中已經(jīng)有該BeanDefinition信息
//1 !isAllowBeanDefinitionOverriding 不允許覆蓋
//2 int ROLE_APPLICATION = 0;
// int ROLE_SUPPORT = 1;
// int ROLE_INFRASTRUCTURE = 2;
//3
if (oldBeanDefinition != null) {
if (!isAllowBeanDefinitionOverriding()) {
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
"Cannot register bean definition [" + beanDefinition + "] for bean '" + beanName +
"': There is already [" + oldBeanDefinition + "] bound.");
}
//log信息省略...
//將原來(lái)的覆蓋
this.beanDefinitionMap.put(beanName, beanDefinition);
}
//原本容器中沒有BeanDefinition信息
else {
//有其他BeanDefinition正在放到容器,等待其他執(zhí)行完畢,ArrayList不是線程安全的
if (hasBeanCreationStarted()) {
// Cannot modify startup-time collection elements anymore (for stable iteration)
//注冊(cè)的過(guò)程中需要線程同步,以保證數(shù)據(jù)的一致性
synchronized (this.beanDefinitionMap) {
//當(dāng)前BeanDefinition放到容器
this.beanDefinitionMap.put(beanName, beanDefinition);
List<String> updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1);
updatedDefinitions.addAll(this.beanDefinitionNames);
updatedDefinitions.add(beanName);
this.beanDefinitionNames = updatedDefinitions;
if (this.manualSingletonNames.contains(beanName)) {
Set<String> updatedSingletons = new LinkedHashSet<>(this.manualSingletonNames);
updatedSingletons.remove(beanName);
this.manualSingletonNames = updatedSingletons;
}
}
}
else {
// Still in startup registration phase
this.beanDefinitionMap.put(beanName, beanDefinition);
this.beanDefinitionNames.add(beanName);
this.manualSingletonNames.remove(beanName);
}
this.frozenBeanDefinitionNames = null;
}
//檢查是否有同名的BeanDefinition已經(jīng)在IOC容器中注冊(cè)
if (oldBeanDefinition != null || containsSingleton(beanName)) {
//重置所有已經(jīng)注冊(cè)過(guò)的BeanDefinition的緩存
resetBeanDefinition(beanName);
}
}
至此IOC流程執(zhí)行完畢,下面總結(jié)畫出調(diào)用時(shí)序圖
以上主要分為三個(gè)流程 定位 加載 注冊(cè)

IOC源碼解析完畢,下次通過(guò)源碼分析,解析DI的過(guò)程