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;
}
相关推荐
写bug写bug几秒前
搞懂MyBatis拦截器的工作原理
java·后端·mybatis
dylan_QAQ3 分钟前
【附录】Spring容器启动流程详解 - prepareRefresh()方法分析
后端·spring
Seven978 分钟前
剑指offer-21、栈的压⼊、弹出序列
java
一只叫煤球的猫9 分钟前
讲讲ResponseEntity的前世今生和水土不服
java·后端·spring
dylan_QAQ12 分钟前
【附录】Spring容器启动流程详解 - obtainFreshBeanFactory()方法分析
后端·spring
架构师沉默12 分钟前
MyBatis 四大组件深度剖析:从原理到实战
java·后端·架构
侧耳倾听11113 分钟前
Java的异常机制
java·开发语言
cccc来财36 分钟前
Spring循环依赖:三级缓存解析
java·后端·spring
zhong liu bin1 小时前
JVM基础【Java】
java·开发语言·jvm·intellij-idea