Spring Bean實例化過程

上篇《Spring類掃描器記錄》中, 記錄了Spring掃描Class, 封裝成一個個BeanDefinition的過程, ApplicationContext後續將根據這些Bean定義來建立Bean實例, BeanDefinition和Bean實例保存在的位置以下:

BeanDefinition保存到的實例變量(DefaultListableBeanFactory):

/** List of bean definition names, in registration order */
List<String> beanDefinitionNames

/** Map from bean name to merged RootBeanDefinition */
Map<String, RootBeanDefinition> mergedBeanDefinitions

Bean實例保存到的成員變量(DefaultListableBeanFactory):

/** 保存單例對象: bean名 --> bean實例 */
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<String, Object>(256);

一個[BeanDefinition]到一個[Bean實例]是經過BeanFactory#getBean方法完成的:

BeanFactory#getBean方法執行過程:

Tags:(BeanFactory具體對應的子類是DefaultListableBeanFactory)segmentfault

  1. 從單例緩存singletonObjects查找, 有則直接返回

沒有則緩存

  1. 建立實例
  2. 執行bean後置處理器,調用Bean初始化方法
    依賴注入是後置處理完成的,也是調用BeanFactory#getBean獲取依賴對象
  3. 保存實例到singletonObjects中

參考百度腦圖: [調用beanFactory.getBean獲取/建立實例]節點3d

問題記錄

1. 實例化Bean的位置

在上下文刷新時AbstractApplicationContext#refreshcode

// 執行徹底部的BeanFactory後置處理
// ConfigurationClassPostProcessor會加載工程下的class到BeanDefinition
// 註冊Bean後置處理器

// 根據BeanDefinition實例化全部單例Bean.
finishBeanFactoryInitialization(beanFactory);

2. 對象循環引用問題

getBean方法經過Bean後置處理器AutowiredAnnotationBeanPostProcessor注入依賴, 該後置處理器又將調用getBean獲取依賴Bean, 例若有以下代碼:對象

@Service
public class ServiceA {
    @Autowired
    ServiceB serviceB;
}

@Service
public class ServiceB {
    @Autowired
    ServiceA serviceA;
}

BeanFactory會將建立中的bean名保存到singletonsCurrentlyInCreation, 建立中的bean實例保存到singletonFactories。token

getBean("serviceA")的過程:

  1. 建立ServiceA實例
  2. 建立ServiceB實例
  3. 實例ServiceA注入到ServiceB (實例ServiceA仍在初始化中)
  4. ServiceB完成建立
  5. 實例ServiceB注入到ServiceA
  6. ServiceA完成建立

被依賴的Bean會先完成初始化
參考圖片連接: Spring循環引用邏輯結構圖圖片

3. 單例Bean建立後註冊到哪了?

DefaultSingletonBeanRegistry對象的singletonObjects字段, 這裏註冊的都是依賴已經注入, 且執行完Bean後置處理器的實例ip

/** Cache of singleton objects: bean name --> bean instance */
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<String, Object>(256);

4. 對象循環依賴異常

BeanCreationException: Circular depends-on relationship between
循環依賴會致使該異常, 如使用@DependsOn註解配置了依賴:get

@Service
@DependsOn("permission")
public class Role {
    @Autowired
    private Permission permission;
}


@Service
@DependsOn("role")
public class Permission {
    @Autowired
    private Role role;
}

Permission,Role互相依賴, 誰沒法被建立, BeanFactory將拋出異常
BeanCreationException:
Circular depends-on relationship between 'role' and 'permission'it

相關文章
相關標籤/搜索