Spring 容器啟動與 Bean 生命周期管理是面試高頻、排查疑難雜癥的核心。本文基於 Spring 5.x 源碼,深度剖析 Prototype Bean 實例化流程、byName/byType 自動裝配實現、FactoryBean getObject 調用鏈路,附關鍵源碼註解與流程圖。
// 單例 Bean 路徑
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, () -> createBean(beanName, mbd, args));
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
// Prototype Bean 路徑
else if (mbd.isPrototype()) {
Object prototypeInstance = null;
try {
beforePrototypeCreation(beanName); // 1. 記錄 ThreadLocal 正在創建
prototypeInstance = createBean(beanName, mbd, args); // 2. 直接創建
} finally {
afterPrototypeCreation(beanName); // 3. 移除 ThreadLocal 記錄
}
bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
}
| 環節 | Singleton | Prototype |
|---|---|---|
| 獲取方式 | getSingleton (先查緩存 singletonObjects) | 直接 createBean |
| 創建前 | 無特殊處理 | beforePrototypeCreation: 記錄到 ThreadLocal prototypesCurrentlyInCreation |
| 創建後 | 加入 singletonObjects、注冊銷毀回調 | afterPrototypeCreation: 從 ThreadLocal 移除 |
| 循環依賴 | 支持 (三級緩存) | 不支持 (每次新建,無早期暴露) |
防止多線程同時創建同一 Prototype Bean 導致狀態混亂,非線程安全保護 (Prototype 本身不保證線程安全)。
protected void autowireByName(String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {
// 1. 找出所有非簡單類型的未滿足屬性 (非基本類型、String、Date 等)
String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
for (String propertyName : propertyNames) {
// 2. 容器中是否存在同名 Bean
if (containsBean(propertyName)) {
// 3. 獲取/創建該 Bean
Object bean = getBean(propertyName);
// 4. 加入屬性值持有器
pvs.add(propertyName, bean);
// 5. 註冊依賴關係 (銷毀順序用)
registerDependentBean(propertyName, beanName);
} else {
// 找不到不報錯,靜默跳過 (byName 特性)
}
}
}
BeanUtils.isSimpleProperty 過濾基本類型、包裝類、String、Date、Class 等AbstractPropertyAccessor.setPropertyValues 遍歷注入protected void autowireByType(String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {
String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
for (String propertyName : propertyNames) {
PropertyDescriptor pd = bw.getPropertyDescriptor(propertyName);
// 跳過 Object 類型屬性 (無意義)
if (!Object.class.equals(pd.getPropertyType())) {
MethodParameter methodParam = BeanUtils.getWriteMethodParameter(pd);
DependencyDescriptor desc = new AutowireByTypeDependencyDescriptor(methodParam, eager);
// 核心解析入口
Object autowiredArgument = resolveDependency(desc, beanName, autowiredBeanNames, converter);
if (autowiredArgument != null) pvs.add(propertyName, autowiredArgument);
}
}
}
findAutowireCandidates → BeanFactoryUtils.beanNamesForTypeIncludingAncestors 獲取所有匹配類型的 Bean 名稱isAutowireCandidate (排除 autowire-candidate=false)getBean(candidateName)required=true 拋 NoSuchBeanDefinitionExceptiondeterminePrimaryCandidate 找 @Primary,無則拋 NoUniqueBeanDefinitionExceptionprotected Object getObjectForBeanInstance(Object beanInstance, String name, String beanName, RootBeanDefinition mbd) {
// 1. & 前綴檢查:名稱以 & 開頭且非 FactoryBean → 報錯
if (BeanFactoryUtils.isFactoryDereference(name) && !(beanInstance instanceof FactoryBean)) {
throw new BeanIsNotAFactoryException(...);
}
// 2. 非 FactoryBean 或要求返回工廠本身 → 直接返回
if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {
return beanInstance;
}
// 3. FactoryBean 處理分支
FactoryBean factory = (FactoryBean) beanInstance;
if (mbd == null) {
// 從緩存獲取 (單例 FactoryBean)
Object object = getCachedObjectForFactoryBean(beanName);
if (object == null) {
object = doGetObjectFromFactoryBean(factory, beanName, !synthetic);
}
return object;
} else {
// 原型/非單例 FactoryBean:每次調用 getObject
return doGetObjectFromFactoryBean(factory, beanName, !synthetic);
}
}
private Object doGetObjectFromFactoryBean(FactoryBean factory, String beanName, boolean shouldPostProcess) {
// 1. 權限檢查 (SecurityManager 環境)
Object object = AccessController.doPrivileged(() -> factory.getObject());
// 2. 空值檢查:單例 FactoryBean 正在創建中返回 null → 報錯
if (object == null && isSingletonCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(...);
}
// 3. 後處理器增強 (如 AOP 代理)
if (object != null && shouldPostProcess) {
object = postProcessObjectFromFactoryBean(object, beanName);
}
return object;
}
| FactoryBean 類型 | isSingleton() | getObject() 執行頻率 | 緩存位置 |
|---|---|---|---|
| Singleton FactoryBean | true | 首次調用後緩存,後續直接返回緓存 | factoryBeanObjectCache (Map) |
| Prototype FactoryBean | false | 每次調用都執行 getObject() 創建新對象 | 無緩存 |
AbstractBeanFactory.doGetBean:統一入口,觀察 scope 分流AbstractAutowireCapableBeanFactory.createBean:實例化、屬性填充、初始化全流程DefaultListableBeanFactory.doResolveDependency:自動裝配核心歧義解決AbstractBeanFactory.getObjectForBeanInstance:FactoryBean 與普通 Bean 分流FactoryBean.getObject:自定義 FactoryBean 斷點驗證邏輯Spring 源碼雖博大,但核心流程清晰:BeanDefinition → 實例化 → 屬性填充 (自動裝配) → 初始化 → 後處理 → 註冊/返回。掌握 Prototype 特殊性、byName/byType 歧義解決、FactoryBean 緩存機制,能解決 90% 容器級疑難雜癥。