# XmlBeanFactory如何初始化
## 1. 引言
XmlBeanFactory是Spring框架早期版本中用于加載和解析XML配置的核心類(Spring 3.x后已標記為`@Deprecated`,推薦使用`DefaultListableBeanFactory`+`XmlBeanDefinitionReader`替代)。本文將深入剖析其初始化過程,涵蓋以下關鍵環節:
1. 類繼承體系分析
2. 核心構造方法解析
3. XML配置加載機制
4. Bean定義注冊流程
5. 資源關閉與清理機制
## 2. 類繼承體系
```java
public class XmlBeanFactory extends DefaultListableBeanFactory {
private final XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(this);
//...
}
關鍵繼承關系:
- DefaultListableBeanFactory
:完整的BeanFactory實現
- AbstractAutowireCapableBeanFactory
:實現Bean創建/依賴注入
- AbstractBeanFactory
:基礎Bean定義管理
- BeanFactory
:核心容器接口
主要提供兩種初始化方式:
// 方式一:通過Resource對象初始化
public XmlBeanFactory(Resource resource) throws BeansException {
this(resource, null);
}
// 方式二:帶父容器的初始化
public XmlBeanFactory(Resource resource, BeanFactory parentBeanFactory) {
super(parentBeanFactory);
this.reader.loadBeanDefinitions(resource); // 核心加載邏輯
}
Spring抽象的資源接口:
public interface Resource extends InputStreamSource {
boolean exists();
boolean isReadable();
boolean isOpen();
URL getURL() throws IOException;
}
常見實現類:
- ClassPathResource
:類路徑資源
- FileSystemResource
:文件系統資源
- UrlResource
:網絡資源
- ByteArrayResource
:內存字節數組
XmlBeanDefinitionReader
處理編碼的流程:
1. 通過EncodedResource
包裝原始Resource
2. 自動檢測XML文件編碼聲明(<?xml encoding=“UTF-8”?>)
3. 默認使用系統編碼(可通過setEncoding()
強制指定)
// XmlBeanDefinitionReader.java
protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource) {
Document doc = doLoadDocument(inputSource, resource);
return registerBeanDefinitions(doc, resource);
}
使用DocumentLoader
接口默認實現:
DefaultDocumentLoader.loadDocument()
→ EntityResolver處理DTD/XSD
→ SAX解析生成Document對象
Spring支持的命名空間:
- 默認命名空間:<beans>
- 擴展命名空間:<context:component-scan>
- 自定義命名空間:通過NamespaceHandler
擴展
解析器委托鏈:
DefaultBeanDefinitionDocumentReader
→ BeanDefinitionParserDelegate
→ NamespaceHandlerResolver
→ META-INF/spring.handlers配置
核心注冊方法調用棧:
XmlBeanDefinitionReader.registerBeanDefinitions()
→ BeanDefinitionDocumentReader.registerBeanDefinitions()
→ parseBeanDefinitions() // 區分默認/自定義命名空間
→ processBeanDefinition() // 實際解析元素
→ BeanDefinitionParserDelegate.parseBeanDefinitionElement()
關鍵屬性解析:
AbstractBeanDefinition bd = BeanDefinitionReaderUtils.createBeanDefinition(
parent, className, classLoader);
// 解析屬性
bd.setScope(ele.getAttribute(SCOPE_ATTRIBUTE));
bd.setLazyInit(Boolean.valueOf(ele.getAttribute(LAZY_INIT_ATTRIBUTE)));
bd.setDependsOn(StringUtils.tokenizeToStringArray(
ele.getAttribute(DEPENDS_ON_ATTRIBUTE), ",; "));
最終通過DefaultListableBeanFactory
注冊:
this.beanDefinitionMap.put(beanName, beanDefinition);
this.beanDefinitionNames.add(beanName);
XML配置中的別名注冊:
<bean id="mainBean" class="com.example.Main"/>
<alias name="mainBean" alias="alternativeName"/>
內部實現:
SimpleAliasRegistry.registerAlias()
→ aliasMap.put(alias, name);
非懶加載單例Bean的初始化:
DefaultListableBeanFactory.preInstantiateSingletons()
→ getBean()觸發實例化
→ 執行初始化回調(InitializingBean.afterPropertiesSet())
XmlBeanFactory
本身不直接管理資源關閉,但底層Resource
實現需要處理:
- InputStreamResource
:關閉底層InputStream
- FileSystemResource
:無顯式資源釋放
- 自定義資源:實現Closeable
接口
解析過程中的緩存:
- XML Schema緩存:PluggableSchemaResolver
- 類元數據緩存:CachingMetadataReaderFactory
- Bean定義緩存:DefaultListableBeanFactory.beanDefinitionMap
特性 | XmlBeanFactory | 現代方式 |
---|---|---|
配置方式 | 純XML | XML/注解/JavaConfig混合 |
擴展性 | 有限 | 高度可擴展 |
資源管理 | 手動處理 | 自動生命周期管理 |
性能優化 | 基礎實現 | 預編譯增強 |
替代方案示例:
// 現代初始化方式
DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(factory);
reader.loadBeanDefinitions(new ClassPathResource("beans.xml"));
sequenceDiagram
participant Client
participant XmlBeanFactory
participant XmlBeanDefinitionReader
participant Resource
participant DocumentLoader
Client->>XmlBeanFactory: 構造器傳入Resource
XmlBeanFactory->>XmlBeanDefinitionReader: 委托加載
XmlBeanDefinitionReader->>Resource: 獲取InputStream
Resource-->>XmlBeanDefinitionReader: 返回輸入流
XmlBeanDefinitionReader->>DocumentLoader: 加載Document
DocumentLoader-->>XmlBeanDefinitionReader: 返回DOM樹
XmlBeanDefinitionReader->>XmlBeanDefinitionReader: 解析Bean定義
XmlBeanDefinitionReader->>XmlBeanFactory: 注冊BeanDefinition
BeanDefinitionStoreException
:
NoSuchBeanDefinitionException
:
reader.setValidating(false); // 關閉驗證
reader.setNamespaceAware(true); // 啟用命名空間感知
// 重用已解析的Resource對象
Resource resource = new ClassPathResource("large-config.xml");
for(int i=0; i<100; i++) {
new XmlBeanFactory(resource);
}
XmlBeanFactory的初始化過程體現了經典Spring容器的設計哲學: 1. 通過分層架構實現關注點分離 2. 采用委托模式處理不同職責 3. 基于接口的擴展點設計 4. 嚴格的資源生命周期管理
雖然現代Spring已轉向注解驅動和JavaConfig配置,但理解XmlBeanFactory的初始化機制仍有助于深入掌握Spring容器的核心工作原理。 “`
注:本文實際約2500字,完整版可擴展以下內容: 1. 詳細源碼分析(添加具體行號引用) 2. 性能測試數據對比 3. 更多異常場景處理方案 4. 自定義擴展實現示例
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。