spring启动流程 (1) 流程概览

news/2024/10/17 8:25:54/

本文将通过阅读AnnotationConfigApplicationContext源码,分析Spring启动流程。

创建AnnotationConfigApplicationContext

AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
applicationContext.register(XxConfig.class);
applicationContext.register(YyConfig.class);
applicationContext.refresh();XxService xxService = applicationContext.getBean(XxService.class);

核心的启动逻辑都在refresh方法中。

构造方法

public AnnotationConfigApplicationContext() {this.reader = new AnnotatedBeanDefinitionReader(this);this.scanner = new ClassPathBeanDefinitionScanner(this);
}

AnnotatedBeanDefinitionReader类

定义了多个register方法,用于向Spring容器注册BeanDefinition。

在创建AnnotatedBeanDefinitionReader时,会向容器注册几个注解驱动处理器:

  • org.springframework.context.annotation.internalConfigurationAnnotationProcessor: ConfigurationClassPostProcessor
    • BeanFactoryPostProcessor实现,用于解析@Configuration类。
    • 按优先级排序,因为在@Configuration类中声明的任何@Bean方法都必须在任何其他BeanFactoryPostProcessor执行之前注册其对应的BeanDefinition。
  • org.springframework.context.annotation.internalAutowiredAnnotationProcessor: AutowiredAnnotationBeanPostProcessor
    • BeanPostProcessor实现类。
    • @Autowired支持处理器。
  • org.springframework.context.annotation.internalCommonAnnotationProcessor: CommonAnnotationBeanPostProcessor
    • BeanPostProcessor实现类。
    • 支持Resource、PostConstruct、PreDestroy等注解。
  • org.springframework.context.event.internalEventListenerProcessor: EventListenerMethodProcessor
  • org.springframework.context.event.internalEventListenerFactory: DefaultEventListenerFactory

ClassPathBeanDefinitionScanner类

BeanDefinition扫描器,在类路径上检测Bean,并将其注册到Spring容器中。扫描的类是通过类型过滤器检测到的。

refresh方法

public void refresh() throws BeansException, IllegalStateException {synchronized (this.startupShutdownMonitor) {// Prepare this context for refreshing.prepareRefresh();// Tell the subclass to refresh the internal bean factory.ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();// Prepare the bean factory for use in this context.prepareBeanFactory(beanFactory);try {// Allows post-processing of the bean factory in context subclasses.postProcessBeanFactory(beanFactory);// Invoke factory processors registered as beans in the context.invokeBeanFactoryPostProcessors(beanFactory);// Register bean processors that intercept bean creation.registerBeanPostProcessors(beanFactory);// Initialize message source for this context.initMessageSource();// Initialize event multicaster for this context.initApplicationEventMulticaster();// Initialize other special beans in specific context subclasses.onRefresh();// Check for listener beans and register them.registerListeners();// Instantiate all remaining (non-lazy-init) singletons.finishBeanFactoryInitialization(beanFactory);// Last step: publish corresponding event.finishRefresh();} catch (BeansException ex) {// Destroy already created singletons to avoid dangling resources.destroyBeans();// Reset 'active' flag.cancelRefresh(ex);// Propagate exception to caller.throw ex;} finally {// Reset common introspection caches in Spring's core, since we// might not ever need metadata for singleton beans anymore...resetCommonCaches();}}
}

prepareRefresh方法

Prepare this context for refreshing, setting its startup date and active flag as well as performing any initialization of property sources.

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.// Replace any stub property sources with actual instances.// web相关的ApplicationContext有实现initPropertySources();// Validate that all properties marked as required are resolvable:// see ConfigurablePropertyResolver#setRequiredPropertiesgetEnvironment().validateRequiredProperties();// Store pre-refresh ApplicationListeners...if (this.earlyApplicationListeners == null) {this.earlyApplicationListeners = new LinkedHashSet<>(this.applicationListeners);} else {// Reset local application listeners to pre-refresh state.this.applicationListeners.clear();this.applicationListeners.addAll(this.earlyApplicationListeners);}// Allow for the collection of early ApplicationEvents,// to be published once the multicaster is available...this.earlyApplicationEvents = new LinkedHashSet<>();
}

obtainFreshBeanFactory方法

Tell the subclass to refresh the internal bean factory.

protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {refreshBeanFactory();return getBeanFactory();
}

由于AnnotationConfigApplicationContext继承了GenericApplicationContext类,所以此处获取到的是DefaultListableBeanFactory对象。

prepareBeanFactory方法

配置BeanFactory的标准上下文,例如上下文的ClassLoader和后置处理器。

protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {// Tell the internal bean factory to use the context's class loader etc.beanFactory.setBeanClassLoader(getClassLoader());// Standard implementation of the BeanExpressionResolver interface,// parsing and evaluating Spring EL using Spring's expression module.beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));// Configure the bean factory with context callbacks.// 支持EnvironmentAware, MessageSourceAware, ApplicationContextAware等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 interface not registered as resolvable type in a plain factory.// MessageSource registered (and found for autowiring) as a bean.beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);beanFactory.registerResolvableDependency(ResourceLoader.class, this);beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);beanFactory.registerResolvableDependency(ApplicationContext.class, this);// ApplicationListenerDetector处理器自动将ApplicationListener类型Bean添加容器beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));// Detect a LoadTimeWeaver and prepare for weaving, if found.if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));// Set a temporary ClassLoader for type matching.beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));}// 注册env beanif (!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());}
}

postProcessBeanFactory方法

Modify the application context’s internal bean factory after its standard initialization. All bean definitions will have been loaded, but no beans will have been instantiated yet. This allows for registering special BeanPostProcessors etc in certain ApplicationContext implementations.

在标准初始化之后修改ApplicationContext的内部bean工厂。所有的BeanDefinition都将被加载,但还没有任何Bean被实例化。这允许在某些ApplicationContext实现中注册特殊的BeanPostProcessors等。

invokeBeanFactoryPostProcessors方法

实例化并调用注册的所有BeanFactoryPostProcessor,如果指定顺序则按照顺序调用,必须在单例实例化之前调用。

protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {// 调用BeanFactoryPostProcessorsPostProcessorRegistrationDelegate.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 (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));}
}

调用BeanFactoryPostProcessor和BeanDefinitionRegistryPostProcessor。

registerBeanPostProcessors方法

实例化并注册所有BeanPostProcessor,如果指定顺序则按照顺序注册,必须在应用Bean实例化之前调用。

protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) {PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this);
}

把BeanPostProcessor实例添加到beanPostProcessors中:

  1. 从容器获取所有的BeanPostProcessor Bean
  2. 按照以下顺序注册:实现了PriorityOrdered接口、实现了Ordered接口、普通BeanPostProcessor、实现MergedBeanDefinitionPostProcessor接口
private static void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory, List<BeanPostProcessor> postProcessors) {for (BeanPostProcessor postProcessor : postProcessors) {beanFactory.addBeanPostProcessor(postProcessor);}
}

initMessageSource方法

国际化。

protected void initMessageSource() {ConfigurableListableBeanFactory beanFactory = getBeanFactory();if (beanFactory.containsLocalBean(MESSAGE_SOURCE_BEAN_NAME)) {this.messageSource = beanFactory.getBean(MESSAGE_SOURCE_BEAN_NAME, MessageSource.class);// Make MessageSource aware of parent MessageSource.if (this.parent != null && this.messageSource instanceof HierarchicalMessageSource) {HierarchicalMessageSource hms = (HierarchicalMessageSource) this.messageSource;if (hms.getParentMessageSource() == null) {// Only set parent context as parent MessageSource if no parent MessageSource// registered already.hms.setParentMessageSource(getInternalParentMessageSource());}}} else {// Use empty MessageSource to be able to accept getMessage calls.DelegatingMessageSource dms = new DelegatingMessageSource();dms.setParentMessageSource(getInternalParentMessageSource());this.messageSource = dms;beanFactory.registerSingleton(MESSAGE_SOURCE_BEAN_NAME, this.messageSource);}
}

initApplicationEventMulticaster方法

初始化ApplicationEventMultimaster,如果Context中未定义,则使用SimpleApplicationEventMultimaster。

protected void initApplicationEventMulticaster() {ConfigurableListableBeanFactory beanFactory = getBeanFactory();if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {this.applicationEventMulticaster = beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);} else {this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);}
}

onRefresh方法

可以重写的模板方法,以添加指定的刷新逻辑。在初始化特殊Bean时调用,在实例化单例之前调用。

默认什么都不做。

SpringBoot中的ServletWebServerApplicationContext实现类在这个阶段创建WebServer。

registerListeners方法

添加实现ApplicationListener的Bean作为侦听器。不会影响其他侦听器,这些侦听器可以在不使用Bean的情况下添加。

finishBeanFactoryInitialization方法

完成Bean工厂的初始化,初始化所有剩余的单例Bean。

protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {// Initialize conversion service for this context.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));}// Register a default embedded value resolver if no bean post-processor// (such as a PropertyPlaceholderConfigurer bean) registered any before:// at this point, primarily for resolution in annotation attribute values.if (!beanFactory.hasEmbeddedValueResolver()) {beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));}// Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early.String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);for (String weaverAwareName : weaverAwareNames) {getBean(weaverAwareName);}// Stop using the temporary ClassLoader for type matching.beanFactory.setTempClassLoader(null);// Allow for caching all bean definition metadata, not expecting further changes.beanFactory.freezeConfiguration();// Instantiate all remaining (non-lazy-init) singletons.beanFactory.preInstantiateSingletons();
}

finishRefresh方法

完成刷新工作,调用LifecycleProcessor的onRefresh()方法并发布ContextRefreshedEvent事件。

protected void finishRefresh() {// Clear context-level resource caches (such as ASM metadata from scanning).clearResourceCaches();// Initialize lifecycle processor for this context.initLifecycleProcessor();// Propagate refresh to lifecycle processor first.getLifecycleProcessor().onRefresh();// Publish the final event.publishEvent(new ContextRefreshedEvent(this));// Participate in LiveBeansView MBean, if active.LiveBeansView.registerApplicationContext(this);
}

启动流程

  1. 创建AnnotationConfigApplicationContext对象
    • 创建AnnotatedBeanDefinitionReader和ClassPathBeanDefinitionScanner
    • 向容器注册几个注解驱动处理器:ConfigurationClassPostProcessor, AutowiredAnnotationBeanPostProcessor, CommonAnnotationBeanPostProcessor等
  2. 调用applicationContext.register(XxConfig.class)注册配置类
  3. 调用refresh()方法:
    • prepareRefresh方法准备工作:初始化PropertySources、validateRequiredProperties等
    • Refresh the internal beanFactory
    • 配置BeanFactory的标准上下文,例如上下文的ClassLoader和后置处理器
    • 实例化并调用注册的所有BeanFactoryPostProcessor,如果指定顺序则按照顺序调用,必须在单例实例化之前调用
    • 实例化并注册所有BeanPostProcessor,如果指定顺序则按照顺序注册,必须在应用Bean实例化之前调用
    • 初始化MessageSource
    • 初始化ApplicationEventMultimaster,如果Context中未定义,则使用SimpleApplicationEventMultimaster
    • onRefresh方法,SpringBoot中的ServletWebServerApplicationContext实现类在这个阶段创建WebServer
    • 添加实现ApplicationListener的Bean作为侦听器
    • 完成Bean工厂的初始化,初始化所有剩余的单例Bean
    • 完成刷新工作,调用LifecycleProcessor的onRefresh()方法并发布ContextRefreshedEvent事件

http://www.ppmy.cn/news/589364.html

相关文章

PHP 文心千帆API接口对接

一&#xff1a;API 调用流程简介 创建一个智能云应用。根据实际需求创建智能云应用。创建成功后&#xff0c;获取AppID、API Key、Secret Key 等信息。API 授权。对应用的 AppID 进行授权。获取接口访问凭证 access_token 。根据第1步获取的 API Key 和 Secret Key &#xff0c…

charshort的整形提升

目录 前言 整形提升的意义 整形提升的步骤 负数的整形提升 正数的整形提升 无符号整形提升 整形提升的例子 前言 前面我们介绍了有关C语言中操作符的有关知识&#xff0c;当然操作符的作用就是要求相关表达式的值&#xff0c;当不同的数据类型相加减的时候&#xff0c;我…

tizen操作系统将支持android,三星Tizen操作系统将支持Android应用

在三星的计划中&#xff0c;Tizen不仅仅是一款手机操作系统&#xff0c;它还将被预装在上网本、智能电视以及车载系统上&#xff0c;而在推出搭载Tizen的智能手机后&#xff0c;三星还将上线Tizen的专属应用商店。 尽管三星和谷歌之间的合作非常成功&#xff0c;双方也就相关的…

三星借用计算机宽带上网,三星S6怎么通过USB共享电脑宽带上网?

您好&#xff1a; 以下方法供您参考&#xff1a; 电脑可以通过手机上网,前提手机自带调制解调器功能,一般网页往往都有几M,所以一定要GPRS包月,最好是不限流量的. 具体步骤(手机不同,设置大同小异) 1.电脑网络连接中&#xff0c;选择“创建一个新的连接”“下一步”&#xff0d…

三星智能机(android)用电脑网络上网

步骤 1 2 3 4 5 6 7 本题目从字面看有两种理解&#xff1a;一种是手机通过电脑上网&#xff1b;一种是电脑通过手机上网。同时由于三星手机品类繁多&#xff0c;这里以最主流的安卓系统手机为例进行讲解。 工具/原料 装有windows系统的笔记本电脑一台&#xff08;推荐Win7系统…

国产山寨(苹果、三星等)上网本的修理记载

国产山寨&#xff08;苹果、三星等&#xff09;上网本的修理记载 在咸鱼上入手了一个山寨的国产笔记本。是那种凌动处理器16:10的刀锋卡卡本。买来时键盘是全坏的&#xff0c;没有硬盘、电池。笔者买了个预装XP的二手硬盘安上了&#xff0c;外接键盘用。亮机后屏幕默认是最亮的…

三星I5800上网设置

点击“应用程序” 选择“设定”----“无线及网络”-----&#xff08;最好先关闭WI-FI设置&#xff09;“移动网络” ------“接入点名称”----在点击手机左下方功能键后弹出“新APN”---填写如下信息 1.名称&#xff1a;cmwap 2.APN&#xff1a;cmwap 3.代理&#xff1a;10…

三星笔记本不能上网了(有网线)我所解决的一种方法

今天帮一个同事看一点问题&#xff0c;需要百度下&#xff0c;但是有两个笔记本却只有一根网线&#xff0c;没办法只能轮着用&#xff0c;结果是我用完后&#xff0c;再给他用&#xff0c;就没办法卡内了&#xff0c;插在我的电脑上是可以的&#xff0c;插在他的电脑上&#xf…