Spring–IOC容器
Spring 是一个基于 Java 平台的开源全栈应用程序框架,也是一个控制反转(IoC)容器实现。
Spring IoC 容器即 Spring 框架中负责管理“Bean”(由容器实例化、配置并组装的普通 POJO 对象)的核心组件。容器读取配置元数据(XML、注解或 Java 配置类),解析 Bean 定义,然后在启动或按需时实例化 Bean,完成依赖注入,并负责 Bean 的整个生命周期管理。
本文章示例代码见该仓库:【spring】中的“spring”模块。
仓库地址:https://gitee.com/quercus-sp204/sourcecode-and-demos
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;@Autowiredpublic 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;@Nullableprivate 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.注册配置类并生成BeanDefinitionrefresh(); // 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类封装成了一个BeanDefinitionAnnotatedGenericBeanDefinition 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. 获取beanFactoryConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();// 3. 准备beanFactory,添加一些组件prepareBeanFactory(beanFactory);try {// 4. 子类扩展设置beanFactorypostProcessBeanFactory(beanFactory);StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");// 5. 执行 BeanFactoryPostProcessor 方法invokeBeanFactoryPostProcessors(beanFactory);// 6. 注册 BeanPostProcessorsregisterBeanPostProcessors(beanFactory);beanPostProcess.end();// 7. 初始化 MessageSource 组件,比如做国际化initMessageSource();// 8. 初始化事件派发器,在注册监听器时会用到initApplicationEventMulticaster();// 9.【模板方法】子类重写这个方法,在容器刷新的时候可以自定义逻辑-// 例如Servlet的容器,里面会启动嵌入的tomcatonRefresh();//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#setRequiredPropertiesgetEnvironment().validateRequiredProperties();....
}
获取beanFactory
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {refreshBeanFactory();return getBeanFactory();
}
返回的是DefaultListableBeanFactory
类型的bean工厂
准备beanFactory
为 BeanFactory
添加通用组件和配置;设置类加载器(ClassLoader
);注册 BeanPostProcessor
(如 ApplicationContextAwareProcessor
);忽略特定接口的自动装配(如 ServletContextAware
)。
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {...beanFactory.setBeanClassLoader(getClassLoader());...// 注册BeanPostProcessorbeanFactory.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()返回上下文配置中显式注册的BeanFactoryPostProcessorPostProcessorRegistrationDelegate.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 {@Overridepublic 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) { // 第一个参数必须是sourcesuper(source);this.message = message;}public String getMessage() {return message;}
}
// 事件发布
@Component(value = "helloEventPublisher")
public class HelloEventPublisher {@Autowiredprivate ApplicationEventPublisher publisher;public void publishEvent(String msg) {HelloEvent event = new HelloEvent(this, msg);publisher.publishEvent(event);}
}
// 监听器1
// 基于注解(支持异步+条件)
@Component
public class HelloEventListener {// 需要开启异步支持// @Async// @EventListenerpublic 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> {@Overridepublic 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);//实例化非延迟单例Beanfor (String beanName : beanNames) {RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {// 处理FactoryBean和非FactoryBeanif (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 {@Autowiredprivate CacheManager cacheManager;@Overridepublic 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. 实例化beanBeanWrapper 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));}// 初始化beanObject 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 源码分析!】