Spring源码解析 - SpringApplication run流程-refreshContext(context)源码分析

refreshContext源码

java 复制代码
//SpringApplication.run 中refreshContext
refreshContext(context);

//SpringApplication.run中refreshContext实现
private void refreshContext(ConfigurableApplicationContext context) {
	if (this.registerShutdownHook) {
		//注册关闭钩子,其实就是注册一个事件监听器
		//发事件的地方在AbstractApplicationContext.class中close()方法的doClose()中publishEvent(new ContextClosedEvent(this));
		shutdownHook.registerApplicationContext(context);
	}
	refresh(context);
}

//SpringApplication.run中refresh实现
protected void refresh(ConfigurableApplicationContext applicationContext) {
	//这里的applicationContext如果没有自己实现上下文,web类项目就是AnnotationConfigServletWebServerApplicationContext
	applicationContext.refresh();
}

//AnnotationConfigServletWebServerApplicationContext一路往上继承自AbstractApplicationContext.class
//这里的AbstractApplicationContext.class就是大部分上下文的父类了。里面有close(关闭流程发ContextClosedEvent关闭事件)和refresh
public void refresh() throws BeansException, IllegalStateException {
    // 确保在启动和关闭过程中只有一个线程可以进入
    synchronized (this.startupShutdownMonitor) {
        // 开始记录上下文刷新的步骤
        StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");

        // 准备上下文以进行刷新
        prepareRefresh();

        // 让子类刷新内部的 BeanFactory
        ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

        // 准备 BeanFactory 以在当前上下文中使用,比较重要,下面有独立解析
        prepareBeanFactory(beanFactory);

        try {
            // 允许子类对 BeanFactory 进行后处理
            postProcessBeanFactory(beanFactory)

            // 开始记录 Bean 后处理的步骤,看到这里
            StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");

            // 调用 BeanFactoryPostProcessor
            invokeBeanFactoryPostProcessors(beanFactory);

            // 注册 BeanPostProcessor
            registerBeanPostProcessors(beanFactory);
            beanPostProcess.end();

            // 初始化消息源
            initMessageSource();

            // 初始化事件多播器
            initApplicationEventMulticaster();

            // 在特定上下文子类中初始化其他特殊 Bean
            onRefresh();

            // 注册监听器
            registerListeners();

            // 实例化所有剩余的(非懒加载)单例
            finishBeanFactoryInitialization(beanFactory);

            // 最后一步:发布相应的事件
            finishRefresh();
        }

        catch (BeansException ex) {
            // 如果在上下文初始化过程中遇到异常,记录警告信息
            if (logger.isWarnEnabled()) {
                logger.warn("Exception encountered during context initialization - " +
                        "cancelling refresh attempt: " + ex);
            }

            // 销毁已经创建的单例,以避免悬挂的资源
            destroyBeans();

            // 重置 'active' 标志
            cancelRefresh(ex);

            // 将异常传播给调用者
            throw ex;
        }

        finally {
            // 重置 Spring 核心中的通用内省缓存,因为我们可能不再需要单例 Bean 的元数据了...
            resetCommonCaches();
            contextRefresh.end();
        }
    }
}

自定义关闭钩子,就是监听ContextClosedEvent事件

开发者可以自定义关闭钩子,通过实现 ApplicationListener 接口并监听 ContextClosedEvent 事件来实现。

java 复制代码
@Component
public class MyShutdownHook implements ApplicationListener<ContextClosedEvent> {
    @Override
    public void onApplicationEvent(ContextClosedEvent event) {
        // 在这里执行自定义的关闭逻辑
        System.out.println("Application is closing...");
        // 例如,关闭数据库连接池
//        DataSource dataSource = event.getApplicationContext().getBean(DataSource.class);
//        if (dataSource instanceof HikariDataSource) {
//            ((HikariDataSource) dataSource).close();
//        }
    }
}

prepareBeanFactory源码解析

java 复制代码
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
    // 设置 BeanFactory 使用当前上下文的类加载器
    beanFactory.setBeanClassLoader(getClassLoader());

    // 如果没有禁用 SpEL 表达式解析器,设置默认的表达式解析器
    if (!shouldIgnoreSpel) {
        beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
    }

    // 注册一个 PropertyEditorRegistrar,用于处理资源路径的解析
    beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));

    // 配置 BeanFactory 的上下文回调
    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);

    // 注册可解析的依赖类型,使得这些接口可以在依赖注入时被解析。
    beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
    beanFactory.registerResolvableDependency(ResourceLoader.class, this);
    beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
    beanFactory.registerResolvableDependency(ApplicationContext.class, this);

    // 注册早期后处理器,用于检测内部 Bean 作为 ApplicationListeners
    beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));

    // 检测 LoadTimeWeaver 并准备织入,如果找到
    if (!NativeDetector.inNativeImage() && 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());
    }
    if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
        beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
    }
    if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
        beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
    }
    if (!beanFactory.containsLocalBean(APPLICATION_STARTUP_BEAN_NAME)) {
        beanFactory.registerSingleton(APPLICATION_STARTUP_BEAN_NAME, getApplicationStartup());
    }
}

小知识点:

beanFactory.registerSingleton和beanFactory.registerResolvableDependency区别

beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));作用

这个在八股文里面比较常见,bean的生命周期,这里就将bean的前后置处理器添加进工厂里面了

add源码(AbstractBeanFactory.class)

java 复制代码
@Override
public void addBeanPostProcessor(BeanPostProcessor beanPostProcessor) {
	Assert.notNull(beanPostProcessor, "BeanPostProcessor must not be null");
	// Remove from old position, if any
	this.beanPostProcessors.remove(beanPostProcessor);
	// Add to end of list,添加处理器
	this.beanPostProcessors.add(beanPostProcessor);
}

BeanPostProcessor使用源码(AbstractBeanFactory.class)自定义BeanPostProcessor也在这里被调用

java 复制代码
//前置
@Override
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
		throws BeansException {

	Object result = existingBean;
	for (BeanPostProcessor processor : getBeanPostProcessors()) { //获取父类beanPostProcessors
		Object current = processor.postProcessBeforeInitialization(result, beanName); //调用前置
		if (current == null) {
			return result;
		}
		result = current;
	}
	return result;
}

//后置处理
@Override
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
		throws BeansException {

	Object result = existingBean;
	for (BeanPostProcessor processor : getBeanPostProcessors()) { //获取父类beanPostProcessors
		Object current = processor.postProcessAfterInitialization(result, beanName); //调用后置
		if (current == null) {
			return result;
		}
		result = current;
	}
	return result;
}
相关推荐
Jul1en_14 小时前
【SpringCloud】SkyWalking 链路追踪知识详解及部署教程
java·后端·spring·spring cloud·skywalking
宸津-代码粉碎机14 小时前
Spring AI 企业级实战|智能记忆摘要+自动遗忘机制落地,彻底解决上下文爆炸与Token冗余
java·大数据·人工智能·后端·python·spring·云计算
逻极14 小时前
Spring Boot 微服务开发提速:我们如何将接口响应时间降低60%
java·spring boot·微服务·性能优化·自动配置
Yvonne爱编码14 小时前
JAVA EE初阶---DAY 2 计算机网络
java·开发语言·计算机网络·算法·java-ee·php
潇凝子潇14 小时前
IDEA插件
java·ide·intellij-idea
摇滚侠14 小时前
SSM 框架实战教程 SpringBoot 自动配置 176-179
java·spring boot·后端
JAVA96514 小时前
JAVA面试-JVM篇 02-G1垃圾收集器的工作原理是什么与CMS的区别
java·jvm·面试
ywl47081208714 小时前
spring单列bean之循环依赖核心源码解读
java·后端·spring
我命由我1234514 小时前
RFID 技术极简理解
java·c语言·c++·嵌入式硬件·物联网·visualstudio·java-ee
格发许可优化管理系统14 小时前
Mentor许可证与其他软件许可证的深度比较
java·大数据·运维·c语言·c++·算法