
在 Java 开发的世界里,Spring 框架无疑是最耀眼的明星,而 Spring 容器则是这颗明星的核心。作为整个应用的 "神经中枢",Spring 容器负责管理 Bean 的生命周期、处理依赖注入、协调各组件之间的交互,支撑着应用的正常运行。
然而,对于许多开发者而言,Spring 容器的启动过程如同一个 "黑箱"—— 我们知道如何配置 Bean,如何使用依赖注入,却对容器从初始化到最终可用经历了哪些步骤知之甚少。这种 "知其然不知其所以然" 的状态,不仅会在遇到问题时束手无策,更会限制我们对 Spring 高级特性的理解和运用。
本文将带您深入 Spring 容器的内部世界,通过源码分析和实战示例,详细拆解容器启动的 10 大核心步骤。无论您是希望提升 Spring 功底的中级开发者,还是追求知根知底的资深工程师,都能从本文中获得对 Spring 容器的全新认知。
在深入分析启动流程之前,我们需要先了解 Spring 容器的核心接口和实现类,这是理解后续流程的基础。
Spring 容器的核心接口主要有两个:BeanFactory和ApplicationContext。
BeanFactory,是更完整的容器接口,除了BeanFactory的功能外,还提供了国际化、事件发布、资源加载等增强功能。它们的核心关系如下:
BeanFactory
↓
HierarchicalBeanFactory
↓
ConfigurableBeanFactory
↓
ApplicationContext
↓
ConfigurableApplicationContext
在实际开发中,我们常用的容器实现类有:
本文将以AnnotationConfigApplicationContext为例进行分析,因为它是现代 Spring 应用(尤其是 Spring Boot)中最常用的容器实现。
Spring 容器的启动过程看似复杂,实则可以分解为 10 个核心步骤。我们将逐一剖析每个步骤的具体操作和源码实现。
容器启动的第一步是创建ApplicationContext实例。以AnnotationConfigApplicationContext为例,这一步会初始化容器的基本组件,如 Bean 定义读取器和类路径扫描器。
示例代码:
@Slf4j
public class ContainerStartupDemo {
public static void main(String[] args) {
// 步骤1:初始化容器实例
log.info("开始初始化AnnotationConfigApplicationContext");
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
log.info("AnnotationConfigApplicationContext实例创建完成");
}
}源码解析(简化版):
public class AnnotationConfigApplicationContext extends GenericApplicationContext implements AnnotationConfigRegistry {
private final AnnotatedBeanDefinitionReader reader;
private final ClassPathBeanDefinitionScanner scanner;
public AnnotationConfigApplicationContext() {
// 创建Bean定义读取器,用于读取注解标注的类
this.reader = new AnnotatedBeanDefinitionReader(this);
// 创建类路径扫描器,用于扫描指定包下的Bean
this.scanner = new ClassPathBeanDefinitionScanner(this);
}
}核心操作:
AnnotatedBeanDefinitionReader:负责将注解标注的类(如@Configuration、@Service)转换为BeanDefinitionClassPathBeanDefinitionScanner:负责扫描指定包路径,发现并注册 Bean容器实例创建后,需要指定配置源 —— 告诉容器从哪里加载 Bean 定义。配置源可以是@Configuration标注的配置类、包路径或 XML 文件等。
示例代码:
@Configuration
@ComponentScan(basePackages = "com.example.demo.service")
public class AppConfig {
@Bean
public UserService userService() {
return new UserService();
}
}
@Service
@Slf4j
public class OrderService {
public void createOrder() {
log.info("创建订单成功");
}
}
@Slf4j
public class ContainerStartupDemo {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
// 步骤2:设置配置源(可以是配置类、包路径等)
log.info("设置配置源");
context.register(AppConfig.class); // 注册配置类
// 或使用扫描包路径:context.scan("com.example.demo");
context.refresh(); // 后续步骤将在refresh()方法中执行
}
}核心操作:
register()方法注册配置类scan()方法指定需要扫描的包路径refresh()方法是容器启动的核心入口,几乎所有关键步骤都在这个方法中完成。它定义在ConfigurableApplicationContext接口中,由具体实现类完成。
源码解析(简化版):
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// 准备刷新
prepareRefresh();
// 获取BeanFactory
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// 准备BeanFactory
prepareBeanFactory(beanFactory);
try {
// 后置处理BeanFactory
postProcessBeanFactory(beanFactory);
// 执行BeanFactory后置处理器
invokeBeanFactoryPostProcessors(beanFactory);
// 注册Bean后置处理器
registerBeanPostProcessors(beanFactory);
// 初始化消息源
initMessageSource();
// 初始化事件多播器
initApplicationEventMulticaster();
// 初始化特定上下文的Bean
onRefresh();
// 注册事件监听器
registerListeners();
// 实例化所有非懒加载单例Bean
finishBeanFactoryInitialization(beanFactory);
// 完成刷新
finishRefresh();
}
// 异常处理...
}
}核心操作:
refresh()方法是一个模板方法,定义了容器启动的整体流程prepareRefresh()方法负责在容器刷新前进行一些准备工作,包括初始化环境、验证必要的属性等。
源码解析(简化版):
protected void prepareRefresh() {
// 记录启动时间和活跃状态
this.startupDate = System.currentTimeMillis();
this.closed.set(false);
this.active.set(true);
// 初始化环境(如.property文件、环境变量等)
initPropertySources();
// 验证所有必要的属性都已设置
getEnvironment().validateRequiredProperties();
// 初始化早期事件集合
if (this.earlyApplicationEvents == null) {
this.earlyApplicationEvents = new LinkedHashSet<>();
}
}示例代码:
@Configuration
@PropertySource("classpath:app.properties") // 加载配置文件
public class AppConfig {
@Value("${app.name}")
private String appName;
@Bean
public UserService userService() {
return new UserService(appName);
}
}
// app.properties
app.name=demo-app
app.required.property=test // 必要属性
@Slf4j
public class UserService {
private final String appName;
public UserService(String appName) {
this.appName = appName;
}
public void printAppName() {
log.info("当前应用名称:{}", appName);
}
}核心操作:
@Required或validateRequiredProperties())obtainFreshBeanFactory()方法负责获取一个新鲜的BeanFactory,对于AnnotationConfigApplicationContext来说,会创建一个DefaultListableBeanFactory实例。
源码解析(简化版):
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
// 刷新BeanFactory
refreshBeanFactory();
// 获取刷新后的BeanFactory
return getBeanFactory();
}
protected final void refreshBeanFactory() throws IllegalStateException {
if (hasBeanFactory()) {
destroyBeans();
closeBeanFactory();
}
try {
// 创建新的BeanFactory实例
DefaultListableBeanFactory beanFactory = createBeanFactory();
beanFactory.setSerializationId(getId());
// 定制BeanFactory(如设置是否允许循环引用、是否允许覆盖Bean定义等)
customizeBeanFactory(beanFactory);
// 加载Bean定义
loadBeanDefinitions(beanFactory);
this.beanFactory = beanFactory;
}
// 异常处理...
}核心操作:
DefaultListableBeanFactory实例(Spring 默认的 Bean 工厂实现)prepareBeanFactory()方法负责配置 BeanFactory 的标准组件,如类加载器、表达式解析器、属性编辑器等。
源码解析(简化版):
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
// 设置类加载器
beanFactory.setBeanClassLoader(getClassLoader());
// 设置表达式解析器
beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
// 添加属性编辑器注册表
beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));
// 添加Bean后置处理器:ApplicationContextAwareProcessor
beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
// 设置忽略自动装配的接口
beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
// ...忽略其他Aware接口
// 注册默认的依赖解析
beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
beanFactory.registerResolvableDependency(ResourceLoader.class, this);
beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
beanFactory.registerResolvableDependency(ApplicationContext.class, this);
// 添加Bean后置处理器:ApplicationListenerDetector
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));
// 注册加载时织入的AspectJ支持
if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
}
// 注册默认的环境Bean
if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
}
// 注册其他默认Bean...
}核心操作:
ApplicationContextAwareProcessor,使 Bean 能感知ApplicationContextEnvironmentAware,它们通过其他方式注入)invokeBeanFactoryPostProcessors()方法负责执行所有注册的BeanFactoryPostProcessor,这些处理器可以修改或增加 Bean 定义。
示例代码:
// 自定义BeanFactoryPostProcessor:修改Bean定义
@Component
@Slf4j
public class CustomBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
log.info("执行CustomBeanFactoryPostProcessor");
// 获取UserService的Bean定义
BeanDefinition beanDefinition = beanFactory.getBeanDefinition("userService");
// 修改Bean定义:设置初始化方法
beanDefinition.setInitMethodName("init");
// 添加属性
MutablePropertyValues propertyValues = beanDefinition.getPropertyValues();
propertyValues.add("version", "1.0.0");
}
}
@Service
@Slf4j
public class UserService {
private String version;
public void setVersion(String version) {
this.version = version;
}
public void init() {
log.info("UserService初始化,版本:{}", version);
}
}源码解析(核心逻辑):
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
// 委托给PostProcessorRegistrationDelegate执行BeanFactoryPostProcessor
PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
// 检查是否有LoadTimeWeaver,如果有则需要当前上下文的类加载器
if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
}
}核心操作:
BeanFactoryPostProcessor,包括:BeanDefinitionRegistryPostProcessor可以注册新的 Bean 定义BeanFactoryPostProcessor可以修改已有的 Bean 定义registerBeanPostProcessors()方法负责注册所有BeanPostProcessor,这些处理器可以在 Bean 实例化的各个阶段对 Bean 进行增强。
示例代码:
// 自定义BeanPostProcessor:在Bean初始化前后添加逻辑
@Component
@Slf4j
public class CustomBeanPostProcessor implements BeanPostProcessor {
// Bean初始化前执行
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if ("userService".equals(beanName)) {
log.info("CustomBeanPostProcessor - 初始化前:{}", beanName);
}
return bean;
}
// Bean初始化后执行
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if ("userService".equals(beanName)) {
log.info("CustomBeanPostProcessor - 初始化后:{}", beanName);
}
return bean;
}
}源码解析(核心逻辑):
protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) {
// 委托给PostProcessorRegistrationDelegate注册BeanPostProcessor
PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this);
}核心操作:
BeanPostProcessor,并按优先级排序BeanPostProcessor可以在 Bean 初始化前后、依赖注入前后等阶段对 Bean 进行增强BeanPostProcessor包括:AutowiredAnnotationBeanPostProcessor(处理 @Autowired)、RequiredAnnotationBeanPostProcessor(处理 @Required)等这一步包括初始化消息源(用于国际化)和事件多播器(用于事件发布与监听),是 Spring 容器的重要基础设施。
源码解析:
protected void initMessageSource() {
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
// 如果存在名为"messageSource"的Bean,则使用它作为消息源
if (beanFactory.containsLocalBean(MESSAGE_SOURCE_BEAN_NAME)) {
this.messageSource = beanFactory.getBean(MESSAGE_SOURCE_BEAN_NAME, MessageSource.class);
if (this.parent != null && this.messageSource instanceof HierarchicalMessageSource) {
HierarchicalMessageSource hms = (HierarchicalMessageSource) this.messageSource;
if (hms.getParentMessageSource() == null) {
hms.setParentMessageSource(getInternalParentMessageSource());
}
}
} else {
// 否则创建默认的消息源
DelegatingMessageSource dms = new DelegatingMessageSource();
dms.setParentMessageSource(getInternalParentMessageSource());
this.messageSource = dms;
beanFactory.registerSingleton(MESSAGE_SOURCE_BEAN_NAME, this.messageSource);
}
}示例代码:
protected void initApplicationEventMulticaster() {
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
// 如果存在名为"applicationEventMulticaster"的Bean,则使用它
if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {
this.applicationEventMulticaster =
beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);
} else {
// 否则创建默认的SimpleApplicationEventMulticaster
this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);
}
}源码解析:
protected void initApplicationEventMulticaster() {
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
// 如果存在名为"applicationEventMulticaster"的Bean,则使用它
if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {
this.applicationEventMulticaster =
beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);
} else {
// 否则创建默认的SimpleApplicationEventMulticaster
this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);
}
}示例代码:
// 自定义事件
public class OrderCreatedEvent extends ApplicationEvent {
private final Long orderId;
public OrderCreatedEvent(Object source, Long orderId) {
super(source);
this.orderId = orderId;
}
public Long getOrderId() {
return orderId;
}
}
// 事件发布者
@Service
public class OrderService {
@Autowired
private ApplicationEventPublisher eventPublisher;
public void createOrder(Long orderId) {
// 创建订单逻辑...
// 发布事件
eventPublisher.publishEvent(new OrderCreatedEvent(this, orderId));
}
}
// 事件监听器
@Component
@Slf4j
public class OrderEventListener {
@EventListener
public void onOrderCreated(OrderCreatedEvent event) {
log.info("收到订单创建事件,订单ID:{}", event.getOrderId());
// 处理事件:如发送通知、更新库存等
}
}核心操作:
初始化消息源,支持国际化消息
finishBeanFactoryInitialization()方法负责实例化所有非懒加载的单例 Bean,这是容器启动过程中最消耗资源的步骤之一。
源码解析(核心逻辑):
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
// 初始化ConversionService(类型转换服务)
if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&
beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
beanFactory.setConversionService(
beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
}
// 注册默认的属性编辑器
if (!beanFactory.hasEmbeddedValueResolver()) {
beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));
}
// 实例化LoadTimeWeaverAware类型的Bean
String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
for (String weaverAwareName : weaverAwareNames) {
getBean(weaverAwareName);
}
// 冻结Bean定义,防止后续修改
beanFactory.freezeConfiguration();
// 实例化所有非懒加载的单例Bean
beanFactory.preInstantiateSingletons();
}Bean 实例化的核心流程:
创建 Bean 实例
BeanNameAware、ApplicationContextAware等postProcessBeforeInitialization()@PostConstruct注解的方法或init-method指定的方法postProcessAfterInitialization()(AOP 代理通常在此处创建)示例代码:
@Service
@Slf4j
public class ProductService implements BeanNameAware {
private String beanName;
// 构造器
public ProductService() {
log.info("ProductService构造器执行");
}
@Autowired
private CategoryService categoryService;
@Override
public void setBeanName(String name) {
this.beanName = name;
log.info("BeanNameAware.setBeanName:{}", name);
}
@PostConstruct
public void init() {
log.info("PostConstruct初始化方法执行");
}
public void queryProduct(Long productId) {
log.info("查询商品,ID:{}", productId);
}
@PreDestroy
public void destroy() {
log.info("PreDestroy销毁方法执行");
}
}执行顺序输出:
ProductService构造器执行
BeanNameAware.setBeanName:productService
PostConstruct初始化方法执行finishRefresh()方法是容器启动的最后一步,主要负责发布容器就绪事件、初始化生命周期处理器等。
源码解析(简化版):
protected void finishRefresh() {
// 初始化生命周期处理器
initLifecycleProcessor();
// 启动所有实现Lifecycle接口的Bean
getLifecycleProcessor().onRefresh();
// 发布ContextRefreshedEvent事件
publishEvent(new ContextRefreshedEvent(this));
// 向MBeanServer注册可管理的Bean(如果开启了JMX)
if (this.registerShutdownHook) {
registerShutdownHook();
}
}示例代码:
// 监听容器刷新完成事件
@Component
@Slf4j
public class ContextRefreshListener {
@EventListener(ContextRefreshedEvent.class)
public void onContextRefreshed(ContextRefreshedEvent event) {
log.info("Spring容器刷新完成,所有Bean已初始化");
ApplicationContext context = event.getApplicationContext();
// 容器就绪后执行一些初始化操作
UserService userService = context.getBean(UserService.class);
userService.initData();
}
}
@Service
@Slf4j
public class UserService {
public void initData() {
log.info("执行初始化数据操作");
}
}核心操作:
初始化生命周期处理器,管理 Bean 的生命周期
ContextRefreshedEvent事件,通知所有监听器容器已就绪为了更直观地理解 Spring 容器的启动流程,我们将上述步骤整理为一个全景图:
容器启动流程
├── 1. 初始化容器实例(new AnnotationConfigApplicationContext())
│ └── 创建AnnotatedBeanDefinitionReader和ClassPathBeanDefinitionScanner
├── 2. 设置配置源(register()或scan())
│ └── 指定配置类或扫描包路径
├── 3. 刷新容器(refresh())
│ ├── 4. 准备刷新(prepareRefresh())
│ │ ├── 初始化环境变量
│ │ └── 验证必要属性
│ ├── 5. 获取BeanFactory(obtainFreshBeanFactory())
│ │ ├── 创建DefaultListableBeanFactory
│ │ └── 加载Bean定义
│ ├── 6. 准备BeanFactory(prepareBeanFactory())
│ │ ├── 配置类加载器、表达式解析器等
│ │ └── 注册ApplicationContextAwareProcessor等
│ ├── 7. 执行BeanFactory后置处理器(invokeBeanFactoryPostProcessors())
│ │ ├── 执行BeanDefinitionRegistryPostProcessor
│ │ └── 执行BeanFactoryPostProcessor
│ ├── 8. 注册Bean后置处理器(registerBeanPostProcessors())
│ │ └── 按优先级注册所有BeanPostProcessor
│ ├── 9. 初始化消息源和事件机制
│ │ ├── 初始化消息源(initMessageSource())
│ │ └── 初始化事件多播器(initApplicationEventMulticaster())
│ ├── 10. 实例化非懒加载单例Bean(finishBeanFactoryInitialization())
│ │ ├── 冻结Bean定义
│ │ └── 按流程实例化所有非懒加载单例Bean
│ └── 11. 完成刷新(finishRefresh())
│ ├── 初始化生命周期处理器
│ ├── 发布ContextRefreshedEvent事件
│ └── 注册关闭钩子
└── 容器启动完成,可用于获取Bean
为了加深对容器启动流程的理解,我们通过一个完整的示例来追踪容器的启动过程。
完整示例代码:
@Configuration
@ComponentScan(basePackages = "com.example.demo")
public class AppConfig {
}@Service
@Slf4j
public class DemoService {
@PostConstruct
public void init() {
log.info("DemoService初始化完成");
}
}@Component
@Slf4j
public class StartupListener {
@EventListener(ContextRefreshedEvent.class)
public void onStartup(ContextRefreshedEvent event) {
log.info("容器启动完成,Bean数量:{}", event.getApplicationContext().getBeanDefinitionCount());
}
}@Slf4j
public class ContainerTrackingDemo {
public static void main(String[] args) {
log.info("开始启动Spring容器");
// 步骤1:初始化容器
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
log.info("容器实例创建完成");
// 步骤2:设置配置源
context.register(AppConfig.class);
log.info("配置源注册完成");
// 步骤3:刷新容器(触发后续所有步骤)
log.info("开始刷新容器");
context.refresh();
log.info("容器刷新完成");
// 使用容器
DemoService demoService = context.getBean(DemoService.class);
log.info("获取到DemoService:{}", demoService);
// 关闭容器
context.close();
}
}执行结果及流程分析:
开始启动Spring容器
容器实例创建完成
配置源注册完成
开始刷新容器
// 步骤4:准备刷新
// 步骤5:获取BeanFactory
// 步骤6:准备BeanFactory
// 步骤7:执行BeanFactory后置处理器
// 步骤8:注册Bean后置处理器
// 步骤9:初始化消息源和事件机制
// 步骤10:实例化非懒加载单例Bean
DemoService初始化完成
// 步骤11:完成刷新
容器启动完成,Bean数量:10
容器刷新完成
获取到DemoService:com.example.demo.service.DemoService@123456
通过这个示例,我们可以清晰地看到容器启动的各个阶段,并验证了之前介绍的核心步骤。
Spring 容器的启动性能对应用的整体性能有重要影响,尤其是在大型应用中。以下是一些常用的优化策略:
@ComponentScan默认会扫描指定包及其子包下的所有类,范围过大会影响启动速度。应尽量缩小扫描范围:
// 不好的做法:扫描范围过大
@ComponentScan(basePackages ="com.example")
// 好的做法:精确到具体子包
@ComponentScan(basePackages ={
"com.example.demo.service",
"com.example.demo.repository"
})
对于非核心 Bean,可使用@Lazy注解延迟初始化,避免在容器启动时实例化:
@Service
@Lazy// 懒加载:第一次使用时才实例化
public class ReportService{
// ...
}
@Conditional根据环境条件注册 Bean@Service
@Conditional(ProductionCondition.class)// 仅在生产环境注册
publicclassProductionMonitoringService{
// ...
}
@PostConstruct)中移走@Service
@Slf4j
public class DataInitializer{
@Async// 异步初始化
@PostConstruct
public void initData(){
log.info("开始异步初始化数据...");
// 耗时的数据初始化操作
}
}
在开发环境中,Spring Boot 的 devtools 可以实现快速重启,大大缩短启动时间:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency>
问题:NoUniqueBeanDefinitionException,提示存在多个同类型的 Bean。
解决方案:
@Primary指定首选 Bean@Qualifier指定具体 Bean 名称@Service
@Primary // 指定为首选Bean
public class PrimaryUserService implements UserService { ... }
@Service
public class SecondaryUserService implements UserService { ... }
// 使用时
@Autowired
private UserService userService; // 会注入PrimaryUserService问题:容器启动时间过长,主要花费在组件扫描阶段。
解决方案:
缩小@ComponentScan的扫描范围
排除不需要扫描的包或类
@ComponentScan(
basePackages = "com.example.demo",
excludeFilters = {
@ComponentScan.Filter(type = FilterType.REGEX, pattern = "com.example.demo.test.*"),
@ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = TestService.class)
}
)
问题:NoSuchBeanDefinitionException,提示找不到指定的 Bean。
解决方案:
@Component、@Service等注解@ComponentScan的扫描范围内// 常见错误:忘记添加@Component注解
public class MissingAnnotationService { ... }
// 正确做法:添加@Component或其派生注解
@Service
public class CorrectService { ... }问题:BeanCurrentlyInCreationException,提示 Bean 正在创建中,出现循环依赖。
解决方案:
@Lazy注解延迟初始化其中一个依赖@Service
public class AService {
private final BService bService;
// 使用@Lazy解决构造器循环依赖
public AService(@Lazy BService bService) {
this.bService = bService;
}
}
@Service
public class BService {
private final AService aService;
public BService(AService aService) {
this.aService = aService;
}
}Spring 容器的启动流程是 Spring 框架的核心知识,掌握这一流程对开发者有多重价值:
BeanFactoryPostProcessor、BeanPostProcessor等扩展点的理解,能够开发出更强大的自定义组件。Spring 容器的启动流程虽然复杂,但并非无章可循。通过本文介绍的 11 个核心步骤,我们可以系统地理解容器从初始化到最终就绪的全过程。无论是refresh()方法的整体框架,还是 Bean 实例化的细节流程,每一部分都体现了 Spring 框架的设计思想。