本文将通过阅读AnnotationConfigApplicationContext源码,分析Spring启动流程。
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);}
定义了多个register方法,用于向Spring容器注册BeanDefinition。
(资料图片)
在创建AnnotatedBeanDefinitionReader时,会向容器注册几个注解驱动处理器:
BeanDefinition扫描器,在类路径上检测Bean,并将其注册到Spring容器中。扫描的类是通过类型过滤器检测到的。
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();}}}
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<>();}
Tell the subclass to refresh the internal bean factory.
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {refreshBeanFactory();return getBeanFactory();}
由于AnnotationConfigApplicationContext继承了GenericApplicationContext类,所以此处获取到的是DefaultListableBeanFactory对象。
配置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());}}
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等。
实例化并调用注册的所有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。
实例化并注册所有BeanPostProcessor,如果指定顺序则按照顺序注册,必须在应用Bean实例化之前调用。
protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) {PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this);}
把BeanPostProcessor实例添加到beanPostProcessors中:
private static void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory, List postProcessors) {for (BeanPostProcessor postProcessor : postProcessors) {beanFactory.addBeanPostProcessor(postProcessor);}}
国际化。
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);}}
初始化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);}}
可以重写的模板方法,以添加指定的刷新逻辑。在初始化特殊Bean时调用,在实例化单例之前调用。
默认什么都不做。
SpringBoot中的ServletWebServerApplicationContext实现类在这个阶段创建WebServer。
添加实现ApplicationListener的Bean作为侦听器。不会影响其他侦听器,这些侦听器可以在不使用Bean的情况下添加。
完成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();}
完成刷新工作,调用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);}
标签:
本文将通过阅读AnnotationConfigApplicationContext源码,分析Spring启
1、小猫可以根据猫的生殖器开口到猫肛门的距离来判断,而公猫和母猫的
直播吧6月26日讯NBA球员库兹马近日在巴黎参加时装周活动。库兹马在活动
来为大家解答以上的问题。赖床的图片,赖床这个很多人还不知道,现在让
尹国富《老师教我们茶文化》。尹国富,男,1954年出生,中共党员,益阳
学生成长问题多元且成因复杂,应该把问题预防作为教育重点。浙江省杭州
诚邀您报名参观2023华南国际工业博览会, 作为华南地区最重要的工业
南阳师范学院河南省近三年艺术类本专科录取分数线2022年:2021年:2020
交易商品牌 产地交货地最新报价D80 99%优等品南京润升石化有限公司国
以下是新劲刚在北京时间6月26日13:21分盘口异动快照:6月26日,新劲刚
厨房改成主卧、主卧一分为二…最令人赞叹的是那么多窗户和满屋阳光,...
塔雷米目前与波尔图的合同还剩下1年,球员拒绝了利雅得新月的报价,因
《蜘蛛侠:纵横宇宙》北美重夺周末冠军《闪电侠》跌幅漫改影史第二高
开奖回顾:第23071期大乐透奖号为02、11、12、32、34+10、12。大小比:
深圳新星:关于“新星转债”评级调整公告
湖北4名货车司机上榜全国“最美货车司机”---6月25日,极目新闻记者...
原标题:工地端午粽飘香,建设者暖心过端午工人日报-中工网记者北梦原
端午节假期前夕,翠亨新区(南朗街道)产业发展再迎里程碑,广东明阳电
6月以来,京津冀地区出现了两次区域性高温天气过程,分别在6月14-18日
今天(6月25日),全球最大、海拔最高的水光互补项目——柯拉一期光...
夏季是溺水事故的高发期,随着气温升高,外出游泳、野外戏水的人增多,
Mfdvdec dllapp是一个应用程序,它是属于MicrosoftWindows操作系统中的
法戒之所以会踏足封神战场,其目的是为替惨死于雷震子之手的徒弟彭遵报
明确164项重点工作 商务部印发《自贸试验区重点工作清单(2023—202
端午假期即将结束今起进入返程高峰预计返程高峰出现在6月24日15时至24
本报讯 (邹仕山 朱旺 杨琦)端午假期,瑞金市一线建设者放弃休息时
荆楚网(湖北日报网)讯(通讯员田胜男)近日,襄阳市中心医院肿瘤微创
中新网广州6月21日电(记者王坚)记者21日从广东省科技厅获悉,该厅重点
停产整顿!陕西两座煤矿被挂牌督办!,近日,记者从榆林市安全生产委员
华商网要闻频道是整合华商报媒体资源,为陕西用户提供24小时全面及时的