spring詳解-IOC
Spring--IOC容器
Spring 是一個基于 Java 平臺的開源全棧應用程序框架,也是一個控制反轉(IoC)容器實現。
Spring IoC 容器即 Spring 框架中負責管理“Bean”(由容器實例化、配置并組裝的普通 POJO 對象)的核心組件。容器讀取配置元數據(XML、注解或 Java 配置類),解析 Bean 定義,然后在啟動或按需時實例化 Bean,完成依賴注入,并負責 Bean 的整個生命周期管理。
本文章示例代碼見該倉庫:【spring】中的“spring”模塊。
1.相關概念
IOC: Inversion of control 【控制反轉】
控制反轉是一種設計原則,其核心思想是:將程序中對象的創建、配置和生命周期管理的控制權,從應用代碼“反轉”交給外部框架或容器來負責。在傳統的程序設計中,業務邏輯代碼主動調用庫或框架完成通用功能;而在 IoC 中,則是框架或容器主動調用開發者編寫的代碼,實現“控制權”反轉,此外呢,IoC 不是一種技術,而是一種思想。
降低組件間的耦合度,提升系統的可維護性和擴展性。例如,傳統開發中Service層直接依賴Dao層的具體實現,而IoC通過容器動態注入依賴,使兩者解耦。
DI:Dependency Injection 【依賴注入】
依賴注入是 IoC 最常見的一種實現方式。在 DI 模式下,對象只需聲明它所依賴的其他對象(通過構造器、屬性或工廠方法),由 IoC 容器在實例化時自動“注入”這些依賴,從而實現組件間的松耦合和可測試性提升。
在Spring中,我們可以通過構造器注入、Setter方法注入或字段注入(如@Autowired)。
// 構造器注入
@Component
public class UserService {
private final UserDao userDao;
@Autowired
public UserService(UserDao userDao) {
this.userDao = userDao;
}
}
2.核心類介紹
我們都知道,spring可以從xml配置文件中解析bean的定義,同時也可以結合相關注解(例如@Configuration, @Bean等)來定義相關bean。最經典的就是這兩種了,下面我們就基于這兩種類型,來介紹一下相關的核心類。
①基本的
- Bean工廠相關接口以及context

上面的類間關系圖我們需要了解的是紅色框框中的三個,BeanFactory、ApplicationEventPublisher、ApplicationContext。
BeanFactory : IOC容器的核心接口,定義了基礎功能(如getBean()、containsBean()),可以看到,BeanFactory是一個頂級接口,定義了比較常用的getBean方法。
public interface BeanFactory {
String FACTORY_BEAN_PREFIX = "&";
Object getBean(String name) throws BeansException;
<T> T getBean(String name, Class<T> requiredType) throws BeansException;
<T> T getBean(Class<T> requiredType) throws BeansException;
boolean containsBean(String name);
.....
}
ApplicationContext:BeanFactory的擴展接口,提供高級功能(如國際化、事件發布、AOP支持)
用于為應用程序提供配置的中央接口。這在應用程序運行時是只讀的,但如果實現支持,則可以重新加載。ApplicationContext提供:
繼承自 ListableBeanFactory用于訪問應用程序組件的 Bean 工廠方法。
繼承自ResourceLoader 接口用以通用方式加載文件資源的能力。
繼承自 ApplicationEventPublisher 接口能夠將事件發布到已注冊的偵聽器。
繼承自 MessageSource 接口 能夠解析消息的能力,支持國際化。
public interface ApplicationContext extends EnvironmentCapable, ListableBeanFactory, HierarchicalBeanFactory,
MessageSource, ApplicationEventPublisher, ResourcePatternResolver {
.....
}
ApplicationEventPublisher:封裝事件發布功能的接口。
@FunctionalInterface
public interface ApplicationEventPublisher {
/*
向在此應用程序注冊過應用程序事件的匹配偵聽器 發送通知。
事件可以是框架事件(例如 ContextRefreshedEvent)或特定于應用程序的事件。
這樣的事件發布步驟實際上是移交給 multicaster,并不意味著同步異步執行,甚至根本不意味著立即執行。
建議事件偵聽器盡可能高效,單獨使用異步執行來執行運行時間較長且可能阻塞的作。
*/
default void publishEvent(ApplicationEvent event) {
publishEvent((Object) event);
}
void publishEvent(Object event); // 接口
}
spring各種類非常多,所以在上圖中,我這里只做出了各自類之間的大致關系。
DefaultListableBeanFactory: Spring IoC 容器的 基礎實現類,直接管理 Bean 的全生命周期(實例化、依賴注入、銷毀);通過BeanDefinitionRegistry 接口注冊/移除 Bean 定義(如 XML 或注解配置);preInstantiateSingletons() 方法來實例化bean。-----這個方法是實現了接口ConfigurableListableBeanFactory
AbstractApplicationContext:是 容器啟動的模板,擴展了企業級功能并依賴 BeanFactory 實現業務邏輯,通過 refresh() 方法定義容器啟動流程(如加載配置、注冊 BeanFactoryPostProcessor)。在其子類實現中,重寫了obtainFreshBeanFactory()方法,可以獲取到beanFactory。
- Bean定義
BeanDefinition 接口用于描述一個 Bean 實例的元信息,包括類名、構造函數參數、屬性值、作用域、初始化/銷毀方法等。
public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {
.....
}
BeanDefinitionHolder 封裝一個 BeanDefinition 以及它對應的 Bean 名稱和別名,可用于內部 Bean 的占位或編程式注冊時攜帶額外信息。
public class BeanDefinitionHolder implements BeanMetadataElement {
private final BeanDefinition beanDefinition;
private final String beanName;
@Nullable
private final String[] aliases;
....
}
BeanDefinitionBuilder 用于以流式 API 構造 GenericBeanDefinition、RootBeanDefinition、ChildBeanDefinition 等,并設置各種屬性(如 scope、lazyInit、autowireMode、initMethod 等)。
②基于注解的context

AnnotationConfigApplicationContext :是 Spring 注解驅動配置的核心實現。其中的關鍵組件:
-
AnnotatedBeanDefinitionReader
負責解析配置類(@Configuration)并注冊 Bean 定義。核心邏輯
- 通過
registerBean()方法將配置類轉換為AnnotatedGenericBeanDefinition。 - 處理
@Bean方法,生成對應的 Bean 定義。 - 注冊
BeanPostProcessor(如ConfigurationClassPostProcessor)。
- 通過
-
ClassPathBeanDefinitionScanner
掃描包路徑下的類,注冊組件(@Component、@Service)。- 過濾條件:默認掃描帶有
@Component及其派生注解的類。 - 擴展點:可通過
includeFilters和excludeFilters自定義過濾規則。
- 過濾條件:默認掃描帶有
該context初始化流程
- 構造階段:
- 創建
DefaultListableBeanFactory(底層 BeanFactory)。 - 初始化
AnnotatedBeanDefinitionReader和ClassPathBeanDefinitionScanner。
- 創建
- 注冊階段:
- 解析配置類,生成
BeanDefinition(如AnnotatedGenericBeanDefinition)。 - 將 Bean 定義注冊到
BeanDefinitionRegistry(即DefaultListableBeanFactory)。
- 解析配置類,生成
- 刷新階段(
refresh()):- 準備環境:驗證配置屬性。
- 獲取 BeanFactory:確保
DefaultListableBeanFactory已初始化。 - 注冊 BeanPostProcessor:如
AutowiredAnnotationBeanPostProcessor。 - 完成 Bean 實例化:通過
preInstantiateSingletons()預加載單例 Bean。
③基于配置文件的context

ClassPathXmlApplicationContext :
- 基于 XML 配置的 Spring 容器:通過加載類路徑(ClassPath)下的 XML 文件初始化 Spring 容器,管理 Bean 的生命周期和依賴注入。
ApplicationContext的實現類:繼承自AbstractApplicationContext,提供完整的容器功能(如國際化、事件機制)。- 傳統 Spring 應用的核心入口:適用于 XML 配置驅動的項目(如早期 Spring 項目)。
示例:
<?xml version="1.0" encoding="UTF-8"?>
<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 scope="singleton" class="com.feng.xmlobj.Policeman" name="policeman">
<constructor-arg name="name" value="國窖001"/>
</bean>
</beans>
public class XmlContextMain {
public static void main(String[] args) {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("all-spring.xml");
Policeman policeman = context.getBean(Policeman.class);
policeman.say();
}
}
// 實體類
public class Policeman {
private String name;
public Policeman(){
System.out.println("Policeman 構造函數");
}
public Policeman(String name){
this.name = name;
}
public void say() {
System.out.println(this.name + "報道!");
}
}
該示例見spring模塊中的帶有xml前綴的類和包。
現在ClassPathXmlApplicationContext用的很少了,現代 Spring 開發更傾向注解配置。
3. 容器創建
在了解到了基本的類,以及他們之間的大致關系之后,這本節我們來探索一下IOC容器是如何創建的。那我們就以注解配置的context為例子。
ApplicationContext context = new AnnotationConfigApplicationContext(Main.class);
Husband h = context.getBean(Husband.class);
h.say();
從構造函數一步一步向下走
// AnnotationConfigApplicationContext.java
public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
this(); // 1.無參構造
register(componentClasses); // 2.注冊配置類并生成BeanDefinition
refresh(); // 3.容器刷新
}
①構造函數
// 1.無參構造
public AnnotationConfigApplicationContext() {
StartupStep createAnnotatedBeanDefReader = getApplicationStartup().start("spring.context.annotated-bean-reader.create");
// 初始化注解 Bean 定義讀取器,通過讀取器預注冊這些處理器,
// 以確保后續注解解析和依賴注入的基礎能力。
/*
創建 AnnotatedBeanDefinitionReader 實例,負責將
注解配置類(如 @Configuration、@Component)轉換為 BeanDefinition
自動注冊關鍵組件:
ConfigurationClassPostProcessor(解析 @Configuration 類)。
AutowiredAnnotationBeanPostProcessor(處理 @Autowired)。
CommonAnnotationBeanPostProcessor(處理 @Resource、@PostConstruct)。
EventListenerMethodProcessor(處理 @EventListener)。
*/
this.reader = new AnnotatedBeanDefinitionReader(this);
createAnnotatedBeanDefReader.end();
/*
創建 ClassPathBeanDefinitionScanner 實例,負責掃描類路徑下的組件類(如 @Component、@Service)
*/
this.scanner = new ClassPathBeanDefinitionScanner(this);
}
在創建AnnotatedBeanDefinitionReader的時候,默認會創建幾個BeanDefinition放到beanDefinitionMap里面。
②注冊配置類
// 2.注冊配置類并生成BeanDefinition
@Override
public void register(Class<?>... componentClasses) {
Assert.notEmpty(componentClasses, "At least one component class must be specified");
StartupStep registerComponentClass = getApplicationStartup().start("spring.context.component-classes.register")
.tag("classes", () -> Arrays.toString(componentClasses));
this.reader.register(componentClasses);
registerComponentClass.end();
}
// AnnotatedBeanDefinitionReader.java
public void register(Class<?>... componentClasses) {
for (Class<?> componentClass : componentClasses) {
registerBean(componentClass);
}
}
// 往下最后是調用下面這個
private <T> void doRegisterBean(Class<T> beanClass, @Nullable String name,
@Nullable Class<? extends Annotation>[] qualifiers, @Nullable Supplier<T> supplier,
@Nullable BeanDefinitionCustomizer[] customizers) {
// 1.看見沒,把Main類封裝成了一個BeanDefinition
AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(beanClass);
if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
return;
}
// 2.這里就相當于在設置BeanDefinition的屬性
abd.setInstanceSupplier(supplier);
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
abd.setScope(scopeMetadata.getScopeName());
String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));
AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);
....
// 3.注冊Bean定義
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
// 通過 BeanDefinitionReaderUtils 將 BeanDefinitionHolder
// 注冊到 BeanFactory 的 beanDefinitionMap 中
BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
}
// BeanDefinitionReaderUtils.java
public static void registerBeanDefinition(
BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
throws BeanDefinitionStoreException {
String beanName = definitionHolder.getBeanName();
// =========這里
registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
String[] aliases = definitionHolder.getAliases();
if (aliases != null) {
for (String alias : aliases) {
registry.registerAlias(beanName, alias);
}
}
}
// GenericApplicationContext.java
@Override
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
throws BeanDefinitionStoreException {
this.beanFactory.registerBeanDefinition(beanName, beanDefinition);
}
// DefaultListableBeanFactory.java
@Override
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
throws BeanDefinitionStoreException {
.....
// 1.從緩存beanDefinitionMap中查
BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName);
if (existingDefinition != null) {
if (!isAllowBeanDefinitionOverriding()) {
throw new BeanDefinitionOverrideException(beanName, beanDefinition, existingDefinition);
}
else if (existingDefinition.getRole() < beanDefinition.getRole()) {
// e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTURE
....
}
else if (!beanDefinition.equals(existingDefinition)) {
....
}
else {
.....
}
this.beanDefinitionMap.put(beanName, beanDefinition);
}
else { // 2.緩存中沒有
// hasBeanCreationStarted()方法是用來檢查此工廠的 bean 創建階段是否已經開始,
// 即在此期間是否有任何 bean 被標記為已創建。此時肯定是沒有任何bean創建了的
if (hasBeanCreationStarted()) {
synchronized (this.beanDefinitionMap) {
this.beanDefinitionMap.put(beanName, beanDefinition);
List<String> updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1);
updatedDefinitions.addAll(this.beanDefinitionNames);
updatedDefinitions.add(beanName);
this.beanDefinitionNames = updatedDefinitions;
removeManualSingletonName(beanName);
}
}
else {
// 放到beanDefinitionMap里面
this.beanDefinitionMap.put(beanName, beanDefinition);
this.beanDefinitionNames.add(beanName);
removeManualSingletonName(beanName);
}
this.frozenBeanDefinitionNames = null;
}
...
}
這一步把主配置類封裝成了一個beanDefinition放進了beanDefinitionMap里面。
③容器刷新【最核心】
refresh()方法是AbstractApplicationContext里面重寫的ConfigurableApplicationContext接口的方法。
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");
// 1. 準備上下文刷新
prepareRefresh();
// 2. 獲取beanFactory
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// 3. 準備beanFactory,添加一些組件
prepareBeanFactory(beanFactory);
try {
// 4. 子類擴展設置beanFactory
postProcessBeanFactory(beanFactory);
StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
// 5. 執行 BeanFactoryPostProcessor 方法
invokeBeanFactoryPostProcessors(beanFactory);
// 6. 注冊 BeanPostProcessors
registerBeanPostProcessors(beanFactory);
beanPostProcess.end();
// 7. 初始化 MessageSource 組件,比如做國際化
initMessageSource();
// 8. 初始化事件派發器,在注冊監聽器時會用到
initApplicationEventMulticaster();
// 9.【模板方法】子類重寫這個方法,在容器刷新的時候可以自定義邏輯-
// 例如Servlet的容器,里面會啟動嵌入的tomcat
onRefresh();
//10.注冊監聽器
registerListeners();
// 11. 創建所有的bean,并且初始化 【最核心的一個方法】
finishBeanFactoryInitialization(beanFactory);
// 12.容器刷新完成,發布一個事件
finishRefresh();
}
catch (BeansException ex) {
// 出現異常的步驟-這里就不看了
}
finally {
resetCommonCaches();
contextRefresh.end();
}
}
}
可以看到,這個方法巨長,里面調用了十幾個方法。加個鎖確保安全性,就沒啥好解釋的了。。。上面有十幾個步驟,其中一些不是很重要的我這里就不去分析了,僅做一個簡要介紹
準備上下文刷新
刷新前的預處理,設置容器狀態并初始化環境。設置 active=true(容器激活)、closed=false。
初始化環境變量(Environment),校驗必填屬性(如數據庫 URL)
protected void prepareRefresh() {
// Switch to active.
this.startupDate = System.currentTimeMillis();
this.closed.set(false);
this.active.set(true);
..
// Initialize any placeholder property sources in the context environment.
initPropertySources();
// Validate that all properties marked as required are resolvable:
// see ConfigurablePropertyResolver#setRequiredProperties
getEnvironment().validateRequiredProperties();
....
}
獲取beanFactory
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
refreshBeanFactory();
return getBeanFactory();
}
返回的是DefaultListableBeanFactory類型的bean工廠
準備beanFactory
為 BeanFactory 添加通用組件和配置;設置類加載器(ClassLoader);注冊 BeanPostProcessor(如 ApplicationContextAwareProcessor);忽略特定接口的自動裝配(如 ServletContextAware)。
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
...
beanFactory.setBeanClassLoader(getClassLoader());
...
// 注冊BeanPostProcessor
beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
beanFactory.ignoreDependencyInterface(ApplicationStartupAware.class);
// Register early post-processor for detecting inner beans as ApplicationListeners.
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));
..
}
子類擴展設置beanFactory
子類擴展點,用于對 BeanFactory 進行后置處理。比如說,Web 環境中注冊 ServletContext 作用域;動態注冊自定義的 BeanDefinition
執行 BeanFactoryPostProcessor 方法
? 執行 BeanFactoryPostProcessor,修改 BeanDefinition,也就是說可以用 BeanFactoryPostProcessor 來定制配置的元數據。這個接口的語義與 BeanPostProcessor 相似,但有一個主要區別: BeanFactoryPostProcessor 在 Bean 配置元數據上運行。也就是說,Spring IoC 容器允許 BeanFactoryPostProcessor 在容器實例化任何 Bean(BeanFactoryPostProcessor 實例除外)之前讀取配置元數據并進行可能的更改。在這里我們只先知道BeanPostProcessor和 BeanFactoryPostProcessor這兩個接口就行了,在后面做具體分析。
? 通過查閱spring官方文檔得知: 我們可以配置多個 BeanFactoryPostProcessor 實例,并可通過設置 order 屬性來控制這些 BeanFactoryPostProcessor 實例的運行順序。但是,只有當 BeanFactoryPostProcessor 實現了 Ordered 接口時,才能設置該屬性。
? invokeBeanFactoryPostProcessors里面大致可以分為兩部分:
1. 處理BeanDefinitionRegistryPostProcessor:優先處理BeanDefinitionRegistryPostProcessor,允許動態注冊Bean定義(如@Configuration類解析)。例如ConfigurationClassPostProcessor,這個就會解析加了@Configuration的配置類,還會解析@ComponentScan、@ComponentScans注解掃描的包,以及解析@Import等注解。
2. 處理BeanFactoryPostProcessor:處理BeanFactoryPostProcessor,僅修改現有Bean定義(如PropertySourcesPlaceholderConfigurer解析占位符)
// AbstractApplicationContext.java
//在Bean實例化之前執行,確保所有'Bean定義'已被后置處理器處理完畢
invokeBeanFactoryPostProcessors(beanFactory);
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
//委托給PostProcessorRegistrationDelegate執行所有后置處理器
// getBeanFactoryPostProcessors()返回上下文配置中顯式注冊的BeanFactoryPostProcessor
PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
// Detect a LoadTimeWeaver and prepare for weaving, if found in the meantime
// (e.g. through an @Bean method registered by ConfigurationClassPostProcessor)
if (!NativeDetector.inNativeImage() && beanFactory.getTempClassLoader() == null &&
beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
}
}
// PostProcessorRegistrationDelegate.java
// 這個方法巨長無比
public static void invokeBeanFactoryPostProcessors(
ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {
// invokeBeanDefinitionRegistryPostProcessors部分
// 解析容器中其他的BeanDefinition,放到eanDefinitionMap里面
// First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered.
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup());
// Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered.
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup());
.....
// 最后一部分
// 執行普通BeanFactoryPostProcessor
// 實現了PriorityOrdered的
// First, invoke the BeanFactoryPostProcessors that implement PriorityOrdered.
sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory); //=====
// Next, invoke the BeanFactoryPostProcessors that implement Ordered.
// 實現了Ordered的
List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());
for (String postProcessorName : orderedPostProcessorNames) {
orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
}
sortPostProcessors(orderedPostProcessors, beanFactory);
invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory); //=====
// 最普通的
// Finally, invoke all other BeanFactoryPostProcessors.
List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());
for (String postProcessorName : nonOrderedPostProcessorNames) {
nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
}
invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory); //=====
// Clear cached merged bean definitions since the post-processors might have
// modified the original metadata, e.g. replacing placeholders in values...
beanFactory.clearMetadataCache();
}
private static void invokeBeanFactoryPostProcessors(
Collection<? extends BeanFactoryPostProcessor> postProcessors, ConfigurableListableBeanFactory beanFactory) {
for (BeanFactoryPostProcessor postProcessor : postProcessors) {
StartupStep postProcessBeanFactory = beanFactory.getApplicationStartup().start("spring.context.bean-factory.post-process").tag("postProcessor", postProcessor::toString);
postProcessor.postProcessBeanFactory(beanFactory); // 調用方法
postProcessBeanFactory.end();
}
}
如下示例使用:
@Configuration
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
BeanDefinition husband = beanFactory.getBeanDefinition("husband");
System.out.println(husband);
}
}
注冊 BeanPostProcessors
registerBeanPostProcessors 方法的主要功能是注冊所有的 BeanPostProcessor 類型的 bean。
protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) {
PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this);
}
實際邏輯由 PostProcessorRegistrationDelegate 類的靜態方法 registerBeanPostProcessors 處理, 將容器中所有 BeanPostProcessor 實例注冊到 BeanFactory,以便后續 Bean 初始化時調用。
同BeanFactoryPostProcessor,也分先后順序:
? 1.PriorityOrdered:最高優先級(如 BeanValidationPostProcessor)。
? 2.Ordered:次高優先級(通過 @Order 注解或實現 Ordered 接口)。
? 3.普通:無順序要求。
初始化 MessageSource 組件
用于初始化國際化(i18n)相關的消息源(MessageSource)
初始化事件派發器
initApplicationEventMulticaster()
主要作用是初始化應用程序事件多播器(ApplicationEventMulticaster)。事件多播器的功能是把應用程序事件(ApplicationEvent)廣播給所有注冊的事件監聽器(ApplicationListener)。
舉個例子:【見倉庫中的 event 包】
public class HelloEvent extends ApplicationEvent { // 定義一個事件
private String message;
public HelloEvent(Object source, String message) { // 第一個參數必須是source
super(source);
this.message = message;
}
public String getMessage() {
return message;
}
}
// 事件發布
@Component(value = "helloEventPublisher")
public class HelloEventPublisher {
@Autowired
private ApplicationEventPublisher publisher;
public void publishEvent(String msg) {
HelloEvent event = new HelloEvent(this, msg);
publisher.publishEvent(event);
}
}
// 監聽器1
// 基于注解(支持異步+條件)
@Component
public class HelloEventListener {
// 需要開啟異步支持
// @Async
// @EventListener
public void handleEvent(HelloEvent helloEvent) {
System.out.println("【(異步方式)事件監聽到了:】" + helloEvent.getMessage());
try {
Thread.sleep(1000);
System.out.println("【(異步方式)事件監聽結束了】");
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
// 條件監聽(僅處理特定用戶)
@EventListener(condition = "#event.message.endsWith('-VIP')")
public void vipNotification(HelloEvent event) {
System.out.println("VIP事件 " + event.getMessage() );
}
}
// 監聽器2
//基于接口(同步監聽)
// @Component
public class InterfaceHelloEventListener implements ApplicationListener<HelloEvent> {
@Override
public void onApplicationEvent(HelloEvent event) {
System.out.println("【基于接口的方式-listener】" + event.getMessage());
}
}
那么,如下場景我們可以考慮用事件發布監聽的方式來實現。
- 電商系統
- 用戶下單 → 發布
OrderCreatedEvent - 監聽器:庫存扣減、優惠券核銷、支付回調
- 用戶下單 → 發布
- 社交平臺
- 用戶發帖 → 發布
PostCreatedEvent - 監聽器:內容審核、推薦算法觸發、消息推送
- 用戶發帖 → 發布
- 微服務架構
- 服務A完成操作 → 發布領域事件
- 服務B通過消息隊列中間件訂閱事件實現最終一致性
自定義邏輯
onRefresh();【模板方法的設計模式】
舉個例子:比如說我們的SpringBoot應用,假如開啟了web支持,在其子類中,會重寫該方法。
// ServletWebServerApplicationContext.java
@Override
protected void onRefresh() {
super.onRefresh();
try {
createWebServer(); // 創建內嵌Tomcat容器
}
catch (Throwable ex) {
throw new ApplicationContextException("Unable to start web server", ex);
}
}
注冊監聽器
將監聽器注冊到事件廣播器(ApplicationEventMulticaster)中,并觸發早期事件的廣播。
protected void registerListeners() {
// 注冊靜態監聽器
// 1.getApplicationListeners返回在 Spring 容器初始化前通過編程方式手動注冊的監聽器
//(例如在配置類中直接添加的監聽器)。
for (ApplicationListener<?> listener : getApplicationListeners()) {
getApplicationEventMulticaster().addApplicationListener(listener);
}
// 2. 注冊 Bean 定義的監聽器
// 獲取所有實現了 ApplicationListener 接口的 Bean 名稱(不實例化 Bean,僅獲取名稱)
String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
for (String listenerBeanName : listenerBeanNames) {
// 通過 Bean 名稱注冊監聽器,延遲到事件觸發時才獲取 Bean 實例
getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
}
// Publish early application events now that we finally have a multicaster...
// 3.發布早期事件
Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
this.earlyApplicationEvents = null;
if (!CollectionUtils.isEmpty(earlyEventsToProcess)) {
for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
getApplicationEventMulticaster().multicastEvent(earlyEvent);
}
}
}
實例所有的bean **【important】
// Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory);
最核心的步驟了,我們順著這個方法,一直往下,可以發現到達了這里。
// AbstractApplicationContext.java
// Instantiate all remaining (non-lazy-init) singletons.
beanFactory.preInstantiateSingletons();
// 實際上是DefaultListableBeanFactory.java 是 BeanFactory的子類實現
@Override
public void preInstantiateSingletons() throws BeansException {
List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
//實例化非延遲單例Bean
for (String beanName : beanNames) {
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
// 處理FactoryBean和非FactoryBean
if (isFactoryBean(beanName)) { // 工廠Bean特殊處理
Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
.....
}
// 觸發普通Bean的實例化與初始化【重點關注的是這個】
else {
/*
getBean()會觸發Bean的實例化、依賴注入、@PostConstruct方法、
InitializingBean.afterPropertiesSet()等初始化邏輯
*/
getBean(beanName);
}
}
}
for (String beanName : beanNames) {
Object singletonInstance = getSingleton(beanName);
// 觸發SmartInitializingSingleton回調
if (singletonInstance instanceof SmartInitializingSingleton) {
StartupStep smartInitialize = getApplicationStartup().start("spring.beans.smart-initialize")
.tag("beanName", beanName);
SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
...
smartSingleton.afterSingletonsInstantiated();
...
smartInitialize.end();
}
}
}
也就是說上面的方法可以分為兩個部分: 1.實例化所有非Lazy的bean;2.觸發SmartInitializingSingleton回調,也就是說,SmartInitializingSingleton接口的afterSingletonsInstantiated()方法在所有單例Bean實例化完成后執行。
SmartInitializingSingleton階段,我們可以做什么呢?舉個簡單的例子:緩存預熱嘛,是吧
@Component
public class CacheWarmupBean implements SmartInitializingSingleton {
@Autowired
private CacheManager cacheManager;
@Override
public void afterSingletonsInstantiated() {
cacheManager.getCache("userCache").putAll(loadInitialData());
}
}
那么,我們重點關注第一個部分中的普通bean的實例化和初始化getBean(beanName)。
// AbstractBeanFactory.java
@Override
public Object getBean(String name) throws BeansException {
return doGetBean(name, null, null, false);
}
protected <T> T doGetBean(
String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
throws BeansException {
// 這個里面只給出關鍵部分
// 1.檢查單例緩存
/*
此步驟會先從單例 Bean 緩存中查找指定名稱的 Bean 實例。
Spring 使用三級緩存機制來管理單例 Bean,這里會嘗試從一級緩存(singletonObjects)、
二級緩存(earlySingletonObjects)和
三級緩存(singletonFactories)中獲取 Bean 實例
*/
// Eagerly check singleton cache for manually registered singletons.
Object sharedInstance = getSingleton(beanName);
...
//3.保證當前 Bean 所依賴的 bean 的初始化。
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
.....
}
//4.Create bean instance.
//4.1 創建單例bean【重點】
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, () -> {
try {
return createBean(beanName, mbd, args);
}
....
});
beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
//4.2 創建原型bean
//4.3 其他
}
可以看到上面的方法大致分為了4步,
首先檢查緩存getSingleton(beanName)本質往下面是調用了DefaultSingletonBeanRegistry的protected Object getSingleton(String beanName, boolean allowEarlyReference) 方法。
第二步,合并 Bean 定義:解析父類或父容器的 Bean 定義(支持繼承) ---- 這個不是很重要,問的gpt:合并Bean定義的核心目的是實現配置的繼承與復用,通過將父Bean的公共配置與子Bean的個性化配置結合,提高代碼的可維護性和靈活性】
第三步,檢查依賴關系【@DependsOn注解】,若 Bean 有依賴的其他 Bean,會先遞歸獲取這些依賴的 Bean 實例,同時檢查是否存在循環依賴。
最后一步就是創建bean了,這里只關注單例bean的創建,調用了重載的方法public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory),第二個參數是一個函數式接口,即對象工廠,里面的getObject()方法就是調用的lambda表達式里面的邏輯如下。
() -> {
try {
return createBean(beanName, mbd, args);
}....
}
搞清楚了這層關系,那我們就來看重載的getSingleton方法
// DefaultSingletonBeanRegistry.java
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
...
synchronized (this.singletonObjects) {
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
...
beforeSingletonCreation(beanName);
boolean newSingleton = false;
boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
if (recordSuppressedExceptions) {
this.suppressedExceptions = new LinkedHashSet<>();
}
try {
// 這一步是調用的上面lambda表達式的createBean(beanName, mbd, args);
singletonObject = singletonFactory.getObject();
newSingleton = true;
}
catch (IllegalStateException ex) {
.....
}
catch (BeanCreationException ex) {
.....
}
finally {
if (recordSuppressedExceptions) {
this.suppressedExceptions = null;
}
afterSingletonCreation(beanName);
}
if (newSingleton) {
// 放入單例池,刪除二三級緩存
addSingleton(beanName, singletonObject);
}
}
return singletonObject;
}
}
// lambda表達式的createBean(beanName, mbd, args);
// AbstractAutowireCapableBeanFactory.java
@Override
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
.....
try {
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
......
return beanInstance;
}
....
}
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
// 1. 實例化bean
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
Object bean = instanceWrapper.getWrappedInstance();
Class<?> beanType = instanceWrapper.getWrappedClass();
if (beanType != NullBean.class) {
mbd.resolvedTargetType = beanType;
}
// Allow post-processors to modify the merged bean definition.
....
// 緩存早期單例,以便能夠解析循環引用
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
if (logger.isTraceEnabled()) {
...
}
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
// 初始化bean
Object exposedObject = bean;
try {
// 依賴注入:屬性填充
populateBean(beanName, mbd, instanceWrapper);
// 執行初始化方法
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
catch (Throwable ex) {
...
}
/*
是在 Bean 創建完成后,檢查并處理該 Bean 的早期單例引用。
如果存在早期單例引用,會根據具體情況對最終暴露的 Bean 對象進行調整,
以確保在循環依賴的場景下,依賴該 Bean 的其他 Bean 使用的是正確版本的 Bean 實例。
就是確保最終所有依賴都指向完全初始化的Bean
*/
if (earlySingletonExposure) {
Object earlySingletonReference = getSingleton(beanName, false);
if (earlySingletonReference != null) {
if (exposedObject == bean) {
exposedObject = earlySingletonReference;
}
else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
String[] dependentBeans = getDependentBeans(beanName);
Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
for (String dependentBean : dependentBeans) {
if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
actualDependentBeans.add(dependentBean);
}
}
..
}
}
}
// Register bean as disposable.
try {
registerDisposableBeanIfNecessary(beanName, bean, mbd);
}
catch (BeanDefinitionValidationException ex) {
...
}
return exposedObject;
}
了解了上面的代碼結構,我們可以理清楚如下思路。

從上圖我們可以看出,bean的創建和初始化等操作,都是在createBean中完成的。
populateBean(beanName, mbd, instanceWrapper):屬性填充
populateBean 是 Spring 框架中用于填充 Bean 屬性的核心方法,負責將 Bean 定義中的屬性值(如依賴注入、配置值等)注入到 Bean 實例中。它是 Bean 生命周期中實例化后、初始化前的關鍵步驟,屬于 AbstractAutowireCapableBeanFactory 類的一部分,屬性注入完成后,才會執行 @PostConstruct 或 InitializingBean.afterPropertiesSet()。
@Autowired 和 @Resource 注解的解析是在調用 InstantiationAwareBeanPostProcessor 的 postProcessProperties 方法時完成的。具體來說,Spring 提供了 AutowiredAnnotationBeanPostProcessor 來處理 @Autowired 注解,CommonAnnotationBeanPostProcessor 來處理 @Resource 注解。
當執行到 InstantiationAwareBeanPostProcessor 的 postProcessProperties 方法時,AutowiredAnnotationBeanPostProcessor 和 CommonAnnotationBeanPostProcessor 會掃描 Bean 類的字段、方法和構造函數,查找帶有 @Autowired 和 @Resource 注解的元素,然后根據注解的配置進行依賴注入。
// 屬性填充大致可以劃分為兩部分
//1.postProcessAfterInstantiation
//這里會遍歷所有實現了 InstantiationAwareBeanPostProcessor 接口的后置處理器,調用它們的 postProcessAfterInstantiation 方法
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
if (!bp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
return;
}
}
}
//2.postProcessProperties【@Autowired 和 @Resource 解析】 && postProcessPropertyValues
//再次遍歷所有實現了 InstantiationAwareBeanPostProcessor 接口的后置處理器,調用它們的 postProcessProperties 方法。
//若該方法返回 null,則進一步調用 postProcessPropertyValues 方法。
for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
PropertyValues pvsToUse = bp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
if (pvsToUse == null) {
....
pvsToUse = bp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
...
}
pvs = pvsToUse;
}
initializeBean(beanName, exposedObject, mbd) : bean初始化
initializeBean 是 Spring 框架中 Bean 生命周期管理的核心方法,負責執行 Bean 的初始化階段。它在 Bean 實例化、屬性填充后觸發,確保 Bean 完成最終的配置和初始化邏輯。
protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
...
// 1.處理 Aware 接口回調
invokeAwareMethods(beanName, bean);
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
// 2.應用 BeanPostProcessor 的前置處理方法
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
try {
// 3. 調用 Bean 的初始化方法
invokeInitMethods(beanName, wrappedBean, mbd);
}
catch (Throwable ex) {
throw new BeanCreationException(
(mbd != null ? mbd.getResourceDescription() : null),
beanName, "Invocation of init method failed", ex);
}
if (mbd == null || !mbd.isSynthetic()) {
// 4.應用 BeanPostProcessor 的后置處理方法【可能會生成代理對象】
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
可以看到bean初始化有大致四個步驟:
-
如果 Bean 實現了
BeanNameAware、BeanFactoryAware等 Aware 接口,調用對應方法 -
遍歷所有
BeanPostProcessor,調用postProcessBeforeInitialization -
調用 Bean 的初始化方法:
@PostConstruct注解的方法;InitializingBean.afterPropertiesSet();XML 配置的init-method -
對初始化后的 Bean 進一步處理(如生成 AOP 代理)
在調試的時候,我們發現在applyBeanPostProcessorsAfterInitialization()方法中出現了如下所示:

執行了AnnotationAwareAspectJAutoProxyCreator類 :: postProcessAfterInitialization() 方法。 它是 Spring AOP 的核心組件之一,負責根據注解(如 @Aspect、@Before)動態生成 AOP 代理。也就是說,Spring IOC 容器創建 bean 實例時,最后都會對 bean 進行處理,來實現增強。對于 Spring AOP 來說,就是創建代理類。 【見后續文章 SpringAOP】
容器刷新完成
protected void finishRefresh() {
// 清除上下文級資源緩存(例如掃描中的 ASM 元數據)-- 不了解
clearResourceCaches();
// 為此上下文初始化生命周期處理器。
initLifecycleProcessor();
// Propagate refresh to lifecycle processor first.
getLifecycleProcessor().onRefresh();
// 發布一個ContextRefreshedEvent事件 --
// 這個可以了解一下【上面也介紹到了事件event】
publishEvent(new ContextRefreshedEvent(this));
// Participate in LiveBeansView MBean, if active.
if (!NativeDetector.inNativeImage()) {
LiveBeansView.registerApplicationContext(this);
}
}
負責完成應用上下文刷新的最后階段,
end.參考
- https://blog.csdn.net/xiaofeng10330111/article/details/85253251 【csdn--張彥峰ZYF--理解IOC與DI】
- https://blog.csdn.net/ivan820819/article/details/79744797 【csdn--ivan820819--淺談IOC--說清楚IOC是什么】
- https://segmentfault.com/a/1190000038438265 【最簡 Spring AOP 源碼分析!】

浙公網安備 33010602011771號