Spring 中 bean 註冊的原始碼解析
前言
所謂 bean 的註冊,就是把在配置檔案中配置的 <bean> 節點載入配記憶體中,供後續使用。
bean的註冊主要分為兩個階段,一個是準備階段,就是對配置檔案進行解析,把配置檔案載入到記憶體中,以 Document 的形式存放;第二個階段是對 Document 進行操作,獲取其中的節點,進行解析,註冊。
類圖
按照慣例,在看原始碼之前,先來看看和 bean 註冊相關的類圖,所涉及到的類比較多,也是挺複雜的,類圖如下所示:
先看看每個類的主要實現,最後再根據一個栗子來看 bean 註冊的主要流程。
1. AliasRegistry :定義了對別名 alias 的簡單增刪改等操作。
2. SimpleAliasRegistry: 它是 AliasRegistry 介面的一個實現類,使用 map 來做 alias 的的對映。
3. BeanDefinitionRegistry :繼承 AliasRegistry 介面, 定義了對 BeanDefinition 的各種增刪改操作。
4. SingletonBeanRegistry :定義對單例bean的註冊和獲取。
5. DefaultSingletonBeanRegistry :是 SingletonBeanRegistry 介面的實現。
6. FactoryBeanRegistrySupport :在 DefaultSingletonBeanRegistry 的基礎上增加了對 FactoryBean 的特殊處理功能。
7. BeanFactory :定義了獲取bean和bean的各種屬性。
8. HierarchicalBeanFactory: 繼承 BeanFactory ,擴充套件了獲取父beanFactory。
9. ConfigurableBeanFactory :提供了配置 Factory 的各種方法。
10. AbstractBeanFactory
11. AutowireCapableBeanFactory:提供建立bean,自動注入,初始化以及應用bean的後置處理器。
12. AbstractAutowireCapableBeanFactory :綜合了 AbstractBeanFactory 並對介面 AutowireCapableBeanFactory 進行實現。
13. ListableBeanFactory :根據各種條件獲取bean的配置清單。
14. ConfigurableListableBeanFactory :BeanFactory 的配置清單,指定忽略型別及介面。
15. DefaultListableBeanFactory :綜合上述所有的功能,主要是對 bean 註冊後的處理。
16. XmlBeanFactory :對 DefaultListableBeanFactory 進行擴充套件,主要使用自定義讀取器 XmlBeanDefinitionReader 從配置檔案中讀取 BeanDefinition。
BeanDefinition
BeanDefinition 是一個介面,它是配置檔案 <bean> 標籤在 Spring 容器中的內部表現形式,<bean> 標籤擁有的屬性也會對應於 BeanDefinition 中的屬性,它們是一一對應的,即一個 <bean> 標籤對應於一個 BeanDefinition 例項。BeanDefinition 相關的類圖如下:
共有三個實現類,在配置檔案中可以有父bean和子bean,父bean用 RootBeanDefinition 來表示,子bean用 ChildBeanDefinition 來表示,而 GenericBeanDefinition 是一個通用的BeanDefinition。
public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {
// .......
void setScope(String scope);
String getScope();
void setLazyInit(boolean lazyInit);
boolean isLazyInit();
void setDependsOn(String... dependsOn);
String[] getDependsOn();
//............
}
AbstractBeanDefinition
AbstractBeanDefinition 實現了 BeanDefinition 介面,在 BeanDefinition 介面中只是定義了<bean>標籤對應屬性的 setter/getter 方法,而沒有定義對應的屬性,而在 AbstractBeanDefinition 類中就定義了對應的各種屬性,並重寫了介面的 setter/getter 方法。:
public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccessor
implements BeanDefinition, Cloneable {
// 一些常量
private volatile Object beanClass;
private String scope = SCOPE_DEFAULT;
private boolean abstractFlag = false;
private boolean lazyInit = false;
private int autowireMode = AUTOWIRE_NO;
private int dependencyCheck = DEPENDENCY_CHECK_NONE;
private String[] dependsOn;
private boolean autowireCandidate = true;
private boolean primary = false;
private final Map<String, AutowireCandidateQualifier> qualifiers = new LinkedHashMap<String, AutowireCandidateQualifier>(0);
private String factoryBeanName;
private String factoryMethodName;
private String initMethodName;
private String destroyMethodName;
private String description;
// setter / getter 方法
}
AliasRegistry
AliasRegistry 定義了對別名 alias 的簡單增刪改等操作。
public interface AliasRegistry {
// 註冊別名
void registerAlias(String name, String alias);
// 刪除別名
void removeAlias(String alias);
// 判斷別名
boolean isAlias(String name);
// 獲取所有別名
String[] getAliases(String name);
}
SimpleAliasRegistry
SimpleAliasRegistry它是 AliasRegistry 介面的一個實現類,使用 map 來做 alias 的的對映。
public class SimpleAliasRegistry implements AliasRegistry {
// 對映的 map
private final Map<String, String> aliasMap = new ConcurrentHashMap<String, String>(16);
// 註冊別名
@Override
public void registerAlias(String name, String alias) {
synchronized (this.aliasMap) {
// 如果真實的名字和別名相同,則把別名移除點,因為真實的名字和別名相同沒有意義
if (alias.equals(name)) {
this.aliasMap.remove(alias);
}
else {
String registeredName = this.aliasMap.get(alias);
// 如果已經註冊過了
if (registeredName != null) {
// 已經註冊過了且別名沒有發生變化,則不處理,沒有必要再註冊一次
if (registeredName.equals(name)) {
return;
}
// 如果別名不允許覆蓋,則丟擲異常
if (!allowAliasOverriding()) {
throw new IllegalStateException("");
}
}
checkForAliasCircle(name, alias);
// 註冊別名
this.aliasMap.put(alias, name);
}
}
}
// 其他的方法都是通過 aliasMap 來判斷的
}
BeanDefinitionRegistry
BeanDefinitionRegistry 繼承 AliasRegistry 介面, 定義了對 BeanDefinition 的各種增刪改操作。
public interface BeanDefinitionRegistry extends AliasRegistry {
// 註冊 BeanDefinition
void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
// 刪除 BeanDefinition
void removeBeanDefinition(String beanName) throws NoSuchBeanDefinitionException;
// 獲取 BeanDefinition
BeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException;
// 是否包含 BeanDefinition
boolean containsBeanDefinition(String beanName);
// 獲取所有 BeanDefinition 的名稱
String[] getBeanDefinitionNames();
// 獲取已經註冊 BeanDefinition 的個數
int getBeanDefinitionCount();
// 該 BeanDefinition 是否已經在登錄檔中使用
boolean isBeanNameInUse(String beanName);
}
SingletonBeanRegistry
SingletonBeanRegistry 定義對單例bean的註冊和獲取。
public interface SingletonBeanRegistry {
// 註冊
void registerSingleton(String beanName, Object singletonObject);
Object getSingleton(String beanName);
boolean containsSingleton(String beanName);
String[] getSingletonNames();
int getSingletonCount();
Object getSingletonMutex();
}
DefaultSingletonBeanRegistry
DefaultSingletonBeanRegistry 是 SingletonBeanRegistry 介面的實現,主要是註冊bean。該類中定義了許多的 集合,用於註冊
public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {
// 如果bean為null則使用 NULL_OBJECT 來站位
protected static final Object NULL_OBJECT = new Object();
// 單例物件快取,bean name --> bean instance
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<String, Object(256);
// 單例對應的工廠快取,可以使用工廠來建立單例物件 bean name --> ObjectFactory
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<String,ObjectFactory<?>>(16);
// 之前的單例物件
private final Map<String, Object> earlySingletonObjects = new HashMap<String, Object>(16);
// 已經註冊過了的單例物件
private final Set<String> registeredSingletons = new LinkedHashSet<String>(256);
// 當前正在建立的單例物件集合
private final Set<String> singletonsCurrentlyInCreation = Collections.newSetFromMap(new ConcurrentHashMap<String, Boolean>(16));
// 需要排除的單例,什麼意思呢?在建立單例的時候,如果該單例正在建立,就不會再建立了,就應該排除掉,如果某個單例在該集合中,則表示該單例正在建立
private final Set<String> inCreationCheckExclusions = Collections.newSetFromMap(new ConcurrentHashMap<String, Boolean>(16));
// ..... 其他的集合 .....
// 註冊單例項的bean
@Override
public void registerSingleton(String beanName, Object singletonObject) throws IllegalStateException {
// 加鎖:為什麼用 ConcurrentHashMap 了還需要加鎖?
synchronized (this.singletonObjects) {
// 判斷是否已經註冊過了,如果註冊過了,則丟擲異常
Object oldObject = this.singletonObjects.get(beanName);
if (oldObject != null) {
throw new IllegalStateException("...");
}
// 註冊
addSingleton(beanName, singletonObject);
}
}
// 真正的註冊邏輯,就是把bean的名稱和物件放到map中
protected void addSingleton(String beanName, Object singletonObject) {
synchronized (this.singletonObjects) {
// 註冊,如果單例物件為null,則使用 NULL_OBJECT 站位
this.singletonObjects.put(beanName, (singletonObject != null ? singletonObject : NULL_OBJECT));
// 該單例物件已經註冊成功,則需要從工廠集合中移除,後面不需要再次註冊
this.singletonFactories.remove(beanName);
// 之前註冊過的物件也移除
this.earlySingletonObjects.remove(beanName);
// 向已經註冊的單例集合中新增該例項
this.registeredSingletons.add(beanName);
}
}
// 根據 beanName 獲取單例物件
@Override
public Object getSingleton(String beanName) {
return getSingleton(beanName, true);
}
// allowEarlyReference 引數是為了解決迴圈引用
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
Object singletonObject = this.singletonObjects.get(beanName);
// 如果該單例沒有註冊過,且正在註冊
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
synchronized (this.singletonObjects) {
// 如果之前也沒有註冊過,且llowEarlyReference=true
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null && allowEarlyReference) {
// 獲取該bean對應的工廠,通過工廠了建立還bean
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
singletonObject = singletonFactory.getObject();
this.earlySingletonObjects.put(beanName, singletonObject);
// 建立成功後,需要去除
this.singletonFactories.remove(beanName);
}
}
}
}
// 返回單例物件
return (singletonObject != NULL_OBJECT ? singletonObject : null);
}
// 獲取所有單例的name
@Override
public String[] getSingletonNames() {
synchronized (this.singletonObjects) {
return StringUtils.toStringArray(this.registeredSingletons);
}
}
// 獲取所有已經註冊了的單例的個數
@Override
public int getSingletonCount() {
synchronized (this.singletonObjects) {
return this.registeredSingletons.size();
}
}
BeanFactory
BeanFactory 它是訪問 Spring 容器的根介面,定義了獲取bean的各種過載方法:
public interface BeanFactory {
// 獲取bean
Object getBean(String name) throws BeansException;
Object getBean(String name, Object... args) throws BeansException;
<T> T getBean(String name, Class<T> requiredType) throws BeansException;
<T> T getBean(Class<T> requiredType) throws BeansException;
<T> T getBean(Class<T> requiredType, Object... args) throws BeansException;
// 是否包含bean
boolean containsBean(String name);
// 是否是單例的bean
boolean isSingleton(String name) throws NoSuchBeanDefinitionException;
// 是否是原型的bean
boolean isPrototype(String name) throws NoSuchBeanDefinitionException;
// 型別是否匹配
boolean isTypeMatch(String name, ResolvableType typeToMatch)
boolean isTypeMatch(String name, Class<?> typeToMatch)
// 返回bean的型別
Class<?> getType(String name) throws NoSuchBeanDefinitionException;
// 獲取bean的所有別名
String[] getAliases(String name);
}
AbstractBeanFactory
AbstractBeanFactory ,它是 BeanFactory 介面的一個抽象實現類,即 綜合了 FactoryBeanRegistrySupport 和 ConfigurableBeanFactory 的功能。
public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport implements ConfigurableBeanFactory {
// bean的後置處理器 BeanPostProcessor 的集合
private final List<BeanPostProcessor> beanPostProcessors = new ArrayList<BeanPostProcessor>();
// 當前正在建立的bean的名稱集合
private final ThreadLocal<Object> prototypesCurrentlyInCreation = new NamedThreadLocal<Object>("Prototype beans currently in creation");
// 其他屬性
// 獲取bean
@Override
public Object getBean(String name) throws BeansException {
return doGetBean(name, null, null, false);
}
public <T> T getBean(String name, Class<T> requiredType, Object... args) throws BeansException{
return doGetBean(name, requiredType, args, false);
}
// 獲取bean,比較複雜,後面介紹了bean註冊過,在來看
protected <T> T doGetBean(final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)throws BeansException {
// 後面分析
}
// 其他方法
}
AbstractAutowireCapableBeanFactory
它繼承了 AbstractBeanFactory 並對介面 AutowireCapableBeanFactory 進行實現,它提供bean建立,屬性填充,自動裝配和初始化。 處理執行時bean引用,解析託管集合,呼叫初始化方法等。此外,它可以按照建構函式,名稱和型別來自動裝配。
該類後面再分析bean的載入時在分析
DefaultListableBeanFactory
在使用 bean 之前,會先註冊所有的 bean,註冊的 bean 就是以 map 的形式放在該類中。從上面的類圖中也可以看到,該類實現了或者說繼承了兩種不同的介面和抽象類,一種是和註冊相關的介面和抽象類,一種是和獲取bean相關的介面,現在只關心和bean註冊相關的部分:
先來看看它定義的一些屬性:
public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable {
// 序列化相關
private static final Map<String, Reference<DefaultListableBeanFactory>> serializableFactories =
new ConcurrentHashMap<String, Reference<DefaultListableBeanFactory>>(8);
private String serializationId;
// 當有相同名稱不同例項時是否允許覆蓋,預設允許
private boolean allowBeanDefinitionOverriding = true;
// 對於賴載入的bean,是否允許立即載入
private boolean allowEagerClassLoading = true;
// bean 註冊的快取,註冊的bean就放在該集合中
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<String, BeanDefinition>(256);
// 根據型別來返回所有bean的name,包含單例和原型兩種模式的bean
private final Map<Class<?>, String[]> allBeanNamesByType = new ConcurrentHashMap<Class<?>, String[]>(64);
// 根據型別返回bean的name,只是返回單例的bean
private final Map<Class<?>, String[]> singletonBeanNamesByType = new ConcurrentHashMap<Class<?>, String[]>(64);
// 註冊的bean的name的集合
private volatile List<String> beanDefinitionNames = new ArrayList<String>(256);
// 手動註冊的單例的 bean name 集合
private volatile Set<String> manualSingletonNames = new LinkedHashSet<String>(16);
// 在凍結配置的情況下快取bean定義名稱陣列
private volatile String[] frozenBeanDefinitionNames;
// 是否可以為所有bean快取bean 的元資料
private volatile boolean configurationFrozen = false;
接下來看下和bean註冊相關的方法:
@Override
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition){
if (beanDefinition instanceof AbstractBeanDefinition) {
// 註冊前的最後一次檢驗,主要是對 AbstractBeanDefinition 的屬性methodOverrides進行校驗
((AbstractBeanDefinition) beanDefinition).validate();
}
BeanDefinition oldBeanDefinition;
oldBeanDefinition = this.beanDefinitionMap.get(beanName);
// 如果已經註冊該bean
if (oldBeanDefinition != null) {
// 如果已經註冊過該bean,且設定為不允許覆蓋,則丟擲異常
if (!isAllowBeanDefinitionOverriding()) {
throw new BeanDefinitionStoreException();
}
// 如果允許覆蓋,則直接註冊,覆蓋
this.beanDefinitionMap.put(beanName, beanDefinition);
}
else {
// 該bean還沒註冊,檢查該工廠的bean建立階段是否已經開始,即在此期間是否已將該bean標記為已建立。如果已經標記為建立
if (hasBeanCreationStarted()) {
// 無法再修改啟動時集合元素(用於穩定迭代)
synchronized (this.beanDefinitionMap) {
this.beanDefinitionMap.put(beanName, beanDefinition);
// 更新 beanDefinitionNames 這個集合
List<String> updatedDefinitions = new
ArrayList<String(this.beanDefinitionNames.size() + 1);
updatedDefinitions.addAll(this.beanDefinitionNames);
updatedDefinitions.add(beanName);
this.beanDefinitionNames = updatedDefinitions;
if (this.manualSingletonNames.contains(beanName)) {
// 安全的從 manualSingletonNames 集合中移除該bean
Set<String> updatedSingletons = new LinkedHashSet<String(this.manualSingletonNames);
updatedSingletons.remove(beanName);
this.manualSingletonNames = updatedSingletons;
}
}
}
else {
// 如果仍然在啟動註冊階段,則直接註冊
this.beanDefinitionMap.put(beanName, beanDefinition);
this.beanDefinitionNames.add(beanName);
this.manualSingletonNames.remove(beanName);
}
this.frozenBeanDefinitionNames = null;
}
}
// 註冊單例的bean
@Override
public void registerSingleton(String beanName, Object singletonObject) {
// 呼叫父類 DefaultSingletonBeanRegistry 的方法進行註冊,上面已經分析過
super.registerSingleton(beanName, singletonObject);
// 同樣的,如果該bean已經標註為開始建立,
if (hasBeanCreationStarted()) {
synchronized (this.beanDefinitionMap) {
if (!this.beanDefinitionMap.containsKey(beanName)) {
// 安全的更新 manualSingletonNames
Set<String> updatedSingletons = new LinkedHashSet<String(this.manualSingletonNames.size() + 1);
updatedSingletons.addAll(this.manualSingletonNames);
updatedSingletons.add(beanName);
this.manualSingletonNames = updatedSingletons;
}
}
}
else {
//直接註冊
if (!this.beanDefinitionMap.containsKey(beanName)) {
this.manualSingletonNames.add(beanName);
}
}
}
栗子
下面通過一個栗子再來看看上面涉及到的類,熟悉 bean 註冊的一個流程
首先,來看一個 bean 配置的全部屬性:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd" >
<bean id="testBean" class="main.tsmyk.pojo.MyTestBean"
abstract="true" autowire="byName" autowire-candidate="true"
depends-on="conversionService" destroy-method="getName"
factory-bean="environment" factory-method=""
init-method="getName" lazy-init="true" name="myTestBean"
parent="environment" primary="true" scope="singleton" >
<property name="name" value=""/>
<constructor-arg name="a" value="a" type="TestBean" index="" ref="">
<bean name="" />
<map key-type="" value-type=""/>
</constructor-arg>
<qualifier value="a" type=""/>
<lookup-method />
<meta key="" value=""/>
<replaced-method/>
</bean>
<alias name="testBean" alias="aaa"/>
<import resource=""/>
</beans>
測試程式碼:
public static void main(String[] args){
BeanFactory beanFactory = new XmlBeanFactory(new ClassPathResource("myspring.xml"));
MyTestBean testBean = (MyTestBean) beanFactory.getBean("testBean");
System.out.println(testBean.getName());
}
第一部分
上面也說了,bean的註冊主要分為兩部分,第一部分載入配置檔案到記憶體形式Document,第二部分對Document的節點進行解析,註冊。這部分不過多的介紹,只需要知道配置檔案載入到記憶體形成 Document 就可以了。
解析配置檔案的時序圖如下所示:
最終,註冊 bean 的邏輯是從 DefaultBeanDefinitionDocumentReader 類的 parseBeanDefinitions() 方法開始的,該方法如下所示:
protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
// 表示的是預設的節點
if (delegate.isDefaultNamespace(root)) {
NodeList nl = root.getChildNodes();
for (int i = 0; i < nl.getLength(); i++) {
Node node = nl.item(i);
if (node instanceof Element) {
Element ele = (Element) node;
if (delegate.isDefaultNamespace(ele)) {
// 解析預設的節點
parseDefaultElement(ele, delegate);
}
else {
// 解析自定義節點
delegate.parseCustomElement(ele);
}
}
}
}
else {
// 解析自定義節點
delegate.parseCustomElement(root);
}
}
在 Spring 的配置檔案中,有兩大類bean的宣告,一個是預設的宣告如 <bean>,一類是自定義的宣告如 <tx:annotation-driver>,所以該方法分為兩套解析邏輯。
預設標籤的解析
預設標籤的解析對應的是 parseDefaultElement() 方法
private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
// 解析 <import>
if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {
importBeanDefinitionResource(ele);
}
// 解析 <alias>
else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {
processAliasRegistration(ele);
}
// 解析 <bean>
else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
processBeanDefinition(ele, delegate);
}
// 解析 <beans>
else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
doRegisterBeanDefinitions(ele);
}
}
<bean> 標籤的解析與註冊
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
// 解析 bean的各種屬性
BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
if (bdHolder != null) {
// 如果該bean包含自定義的子標籤,則對自定義子標籤解析
bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
// 註冊
BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
// 發訊息,可以忽略
getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
}
}
解析bean的屬性和子節點
public BeanDefinitionHolder parseBeanDefinitionElement(Element ele) {
return parseBeanDefinitionElement(ele, null);
}
//containingBean: 父 bean
public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, BeanDefinition containingBean) {
// id 屬性
String id = ele.getAttribute(ID_ATTRIBUTE);
// name 屬性
String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);
// name 屬性值就是別名 alias,解析 name 的值,放到 alias 集合中,
List<String> aliases = new ArrayList<String>();
if (StringUtils.hasLength(nameAttr)) {
// 這裡可以看到 name 的值可以使用 , ; 和空格進行分割
String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, ",; ");
aliases.addAll(Arrays.asList(nameArr));
}
// beanName 的值就是 id 的值
String beanName = id;
// 如果 beanName 為空,且 alias 不為空,則獲取第一個別名作為beanName
if (!StringUtils.hasText(beanName) && !aliases.isEmpty()) {
beanName = aliases.remove(0);
}
// 如果父 bean 為空,則檢查beanName的唯一性
if (containingBean == null) {
checkNameUniqueness(beanName, aliases, ele);
}
// 建立 AbstractBeanDefinition 在該方法內部,會解析bean所有的屬性和子節點
AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean);
if (beanDefinition != null) {
if (!StringUtils.hasText(beanName)) {
// 如果 beanName為空,則根據spring中的命名規則為該bean生成對應的beanName
if (containingBean != null) {
beanName = BeanDefinitionReaderUtils.generateBeanName(beanDefinition, this.readerContext.getRegistry(), true);
}
else {
beanName = this.readerContext.generateBeanName(beanDefinition);
// 把該bean的類名也註冊為別名,為了向後相容
String beanClassName = beanDefinition.getBeanClassName();
if (beanClassName != null && beanName.startsWith(beanClassName) && beanName.length() > beanClassName.length() &&!this.readerContext.getRegistry().isBeanNameInUse(beanClassName)) {
aliases.add(beanClassName);
}
}
}
// BeanDefinitionHolder 建立物件返回,分別設定對應的屬性值
String[] aliasesArray = StringUtils.toStringArray(aliases);
return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray);
}
return null;
}
// 解析屬性和子節點
public AbstractBeanDefinition parseBeanDefinitionElement(Element ele, String beanName, BeanDefinition containingBean) {
// 不知道幹嘛用
this.parseState.push(new BeanEntry(beanName));
// 獲取 class 屬性的值
String className = null;
if (ele.hasAttribute(CLASS_ATTRIBUTE)) {
className = ele.getAttribute(CLASS_ATTRIBUTE).trim();
}
// 獲取 parent 屬性的值
String parent = null;
if (ele.hasAttribute(PARENT_ATTRIBUTE)) {
parent = ele.getAttribute(PARENT_ATTRIBUTE);
}
// 建立 AbstractBeanDefinition 物件,底層是 GenericBeanDefinition
AbstractBeanDefinition bd = createBeanDefinition(className, parent);
// 解析所有屬性
parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);
bd.setDescription(DomUtils.getChildElementValueByTagName(ele, DESCRIPTION_ELEMENT));
// 解析 <meta>
parseMetaElements(ele, bd);
// 解析 <lookup-method />
parseLookupOverrideSubElements(ele, bd.getMethodOverrides());
// 解析 <replaced-method/>
parseReplacedMethodSubElements(ele, bd.getMethodOverrides());
// 解析 <constructor-arg />
parseConstructorArgElements(ele, bd);
// 解析 <property />
parsePropertyElements(ele, bd);
// 解析 <qualifier />
parseQualifierElements(ele, bd);
bd.setResource(this.readerContext.getResource());
bd.setSource(extractSource(ele));
return bd;
}
// 解析所有屬性
public AbstractBeanDefinition parseBeanDefinitionAttributes(Element ele, String beanName,
BeanDefinition containingBean, AbstractBeanDefinition bd) {
// singleton 和 scope 只能有一個
if (ele.hasAttribute(SINGLETON_ATTRIBUTE)) {
error("Old 1.x 'singleton' attribute in use - upgrade to 'scope' declaration", ele);
}
else if (ele.hasAttribute(SCOPE_ATTRIBUTE)) {
bd.setScope(ele.getAttribute(SCOPE_ATTRIBUTE));
}
else if (containingBean != null) {
bd.setScope(containingBean.getScope());
}
// abstract 屬性
if (ele.hasAttribute(ABSTRACT_ATTRIBUTE)) {
bd.setAbstract(TRUE_VALUE.equals(ele.getAttribute(ABSTRACT_ATTRIBUTE)));
}
// lazyInit 屬性
String lazyInit = ele.getAttribute(LAZY_INIT_ATTRIBUTE);
if (DEFAULT_VALUE.equals(lazyInit)) {
lazyInit = this.defaults.getLazyInit();
}
bd.setLazyInit(TRUE_VALUE.equals(lazyInit));
// 其他屬性
}
// 解析 <meta>
public void parseMetaElements(Element ele, BeanMetadataAttributeAccessor attributeAccessor) {
NodeList nl = ele.getChildNodes();
for (int i = 0; i < nl.getLength(); i++) {
Node node = nl.item(i);
// 判斷是 meta 節點
if (isCandidateElement(node) && nodeNameEquals(node, META_ELEMENT)) {
Element metaElement = (Element) node;
String key = metaElement.getAttribute(KEY_ATTRIBUTE);
String value = metaElement.getAttribute(VALUE_ATTRIBUTE);
BeanMetadataAttribute attribute = new BeanMetadataAttribute(key, value);
attribute.setSource(extractSource(metaElement));
attributeAccessor.addMetadataAttribute(attribute);
}
}
}
// 其他節點的解析類似
當解析完bean的所有屬性和子節點後,得到 BeanDefinitionHolder 物件,該物件中包含了 bean 定義的的全部資訊,之後會對該物件進行包裝,為什麼需要進行包裝的?如果配置的bean有子節點,且該子節點是使用者自定義的節點,則會對該子節點進行包裝:
bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
public BeanDefinitionHolder decorateBeanDefinitionIfRequired(Element ele, BeanDefinitionHolder definitionHolder) {
return decorateBeanDefinitionIfRequired(ele, definitionHolder, null);
}
// 包裝,containingBd:父bean
public BeanDefinitionHolder decorateBeanDefinitionIfRequired(Element ele, BeanDefinitionHolder definitionHolder, BeanDefinition containingBd) {
// 最終的 BeanDefinitionHolder
BeanDefinitionHolder finalDefinition = definitionHolder;
// 遍歷所有屬性,看看否是有適用於修改的屬性
NamedNodeMap attributes = ele.getAttributes();
for (int i = 0; i < attributes.getLength(); i++) {
Node node = attributes.item(i);
finalDefinition = decorateIfRequired(node, finalDefinition, containingBd);
}
// 遍歷所有子節點,看看是否有適用於修改的子節點
NodeList children = ele.getChildNodes();
for (int i = 0; i < children.getLength(); i++) {
Node node = children.item(i);
if (node.getNodeType() == Node.ELEMENT_NODE) {
finalDefinition = decorateIfRequired(node, finalDefinition, containingBd);
}
}
return finalDefinition;
}
public BeanDefinitionHolder decorateIfRequired(
Node node, BeanDefinitionHolder originalDef, BeanDefinition containingBd) {
// 獲取自定義的名稱空間
String namespaceUri = getNamespaceURI(node);
// 不是預設的名稱空間,則是自定義的名稱空間
if (!isDefaultNamespace(namespaceUri)) {
// 根據名稱空間獲取對應的處理器
NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);
if (handler != null) {
return handler.decorate(node, originalDef, new ParserContext(this.readerContext, this, containingBd));
}
}
return originalDef;
}
到這裡bean的定義解析完畢了,接下來就是把解析後的bean註冊到Spring容器中了:
BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
// 註冊
public static void registerBeanDefinition(BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry) throws BeanDefinitionStoreException {
// bean的名字
String beanName = definitionHolder.getBeanName();
// 使用 DefaultListableBeanFactory 來註冊bean,即把beanName和對應的BeanDefinition 註冊到map中,上面分析DefaultListableBeanFactory 類時已經分析過該方法了
registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
// 註冊別名,呼叫 SimpleAliasRegistry 的 registerAlias 來註冊別名,上面已經分析該類了
String[] aliases = definitionHolder.getAliases();
if (aliases != null) {
for (String alias : aliases) {
registry.registerAlias(beanName, alias);
}
}
}
到這裡 <bean> 標籤的註冊已經分析完畢了,還剩下 <import>,<alias> 和 </beans> 標籤的解析,關於 <alias> 標籤的註冊,在上述分析 SimpleAliasRegistry 就分析過了,剩下的兩個也是同樣的套路。
到這裡,關於bean的註冊就分析完畢了。