SpringBoot 启动类 SpringApplication 三 设置IOC容器

[复制链接]
发表于 2025-11-18 04:00:01 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×
设置IOC容器

  1. public ConfigurableApplicationContext run(String... args) {
  2.         // -- snip
  3.                 try {
  4.                         // context的类型是AnnotationConfigServletWebServerApplicationContext
  5.                         context = createApplicationContext();
  6.                         context.setApplicationStartup(this.applicationStartup);
  7.                         // 1. 准备容器
  8.                         prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);
  9.                         // 2. 刷新容器
  10.                         refreshContext(context);
  11.                         afterRefresh(context, applicationArguments);
  12.                         startup.started();
  13.                         if (this.logStartupInfo) {
  14.                                 new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), startup);
  15.                         }
  16.                         listeners.started(context, startup.timeTakenToStarted());
  17.                         callRunners(context, applicationArguments);
  18.                 }
  19.                 catch (Throwable ex) {
  20.                         throw handleRunFailure(context, ex, listeners);
  21.                 }
  22.                 try {
  23.                         if (context.isRunning()) {
  24.                                 listeners.ready(context, startup.ready());
  25.                         }
  26.                 }
  27.                 catch (Throwable ex) {
  28.                         throw handleRunFailure(context, ex, null);
  29.                 }
  30.                 return context;
  31.         }
复制代码
1. 准备容器

  1. private void prepareContext(DefaultBootstrapContext bootstrapContext, ConfigurableApplicationContext context,
  2.                 ConfigurableEnvironment environment, SpringApplicationRunListeners listeners,
  3.                 ApplicationArguments applicationArguments, Banner printedBanner) {
  4.         context.setEnvironment(environment);
  5.         // 配置容器的类加载器、资源加载器、类型转换器
  6.         postProcessApplicationContext(context);
  7.         // 如果JVM允许AOT,则配置AOT相关的ApplicationContextInitializer
  8.         // AOT(ahead of time)是在程序运行前将字节码编译成机器码,JIT(just in time)是程序边运行边将字节码编译成机器码。普通SpringBoot用的是JIT
  9.         addAotGeneratedInitializerIfNecessary(this.initializers);
  10.         // 1. 执行初始化器
  11.         applyInitializers(context);
  12.         listeners.contextPrepared(context);
  13.         // 关闭引导上下文
  14.         bootstrapContext.close(context);
  15.         if (this.logStartupInfo) {
  16.                 logStartupInfo(context.getParent() == null);
  17.                 logStartupProfileInfo(context);
  18.         }
  19.         // Add boot specific singleton beans
  20.         // beanFactory的类型是DefaultListableBeanFactory
  21.         ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
  22.         // 向bean工厂注册单例applicationArguments
  23.         beanFactory.registerSingleton("springApplicationArguments", applicationArguments);
  24.         if (printedBanner != null) {
  25.                 beanFactory.registerSingleton("springBootBanner", printedBanner);
  26.         }
  27.         if (beanFactory instanceof AbstractAutowireCapableBeanFactory autowireCapableBeanFactory) {
  28.                 // 配置是否允许循环依赖
  29.                 autowireCapableBeanFactory.setAllowCircularReferences(this.allowCircularReferences);
  30.                 if (beanFactory instanceof DefaultListableBeanFactory listableBeanFactory) {
  31.                         listableBeanFactory.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
  32.                 }
  33.         }
  34.         if (this.lazyInitialization) {
  35.                 // 设置延迟加载
  36.                 context.addBeanFactoryPostProcessor(new LazyInitializationBeanFactoryPostProcessor());
  37.         }
  38.         if (this.keepAlive) {
  39.                 // KeepAlive()对象额外启动一个非守护线程,避免`SpringBoot`因为非守护线程结束而关闭JVM
  40.                 context.addApplicationListener(new KeepAlive());
  41.         }
  42.         // PropertySourceOrderingBeanFactoryPostProcessor是对@PropertySource注解修饰的类进行排序
  43.         context.addBeanFactoryPostProcessor(new PropertySourceOrderingBeanFactoryPostProcessor(context));
  44.         if (!AotDetector.useGeneratedArtifacts()) {
  45.                 // Load the sources
  46.                 Set<Object> sources = getAllSources();
  47.                 Assert.notEmpty(sources, "Sources must not be empty");
  48.                 load(context, sources.toArray(new Object[0]));
  49.         }
  50.         listeners.contextLoaded(context);
  51. }
复制代码
1. 实行初始化器

  1. protected void applyInitializers(ConfigurableApplicationContext context) {
  2.         for (ApplicationContextInitializer initializer : getInitializers()) {
  3.                 Class<?> requiredType = GenericTypeResolver.resolveTypeArgument(initializer.getClass(),
  4.                                 ApplicationContextInitializer.class);
  5.                 Assert.isInstanceOf(requiredType, context, "Unable to call initializer.");
  6.                 initializer.initialize(context);
  7.         }
  8. }
复制代码
SpringBoot默认的初始化器有7个。从上到下它们的功能分别是
0. 实行情况属性context.initializer.classes指定的初始化器。它的优先级最高。

  • 向容器添加一个CachingMetadataReaderFactoryPostProcessor。
  • 初始化容器的ID。
  • 向容器增长一个处理处罚错误告警的BeanFactoryPostProcessor。
  • RSocket是基于Reactive Streams的通讯协议。
  • 向容器设置server.port端口属性。
  • 向容器中设置ConditionEvaluationReportListener。

2.革新容器


终极调用的是AbstractApplicationContext#refresh()方法。
  1. private final Lock startupShutdownLock = new ReentrantLock();
  2. public void refresh() throws BeansException, IllegalStateException {
  3.         // startupShutdownLock锁是防止当前线程刷新容器,别的线程关闭容器。
  4.         this.startupShutdownLock.lock();
  5.         try {
  6.                 this.startupShutdownThread = Thread.currentThread();
  7.                 StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");
  8.                 // Prepare this context for refreshing.
  9.                 // 1. 准备刷新
  10.                 prepareRefresh();
  11.                 // Tell the subclass to refresh the internal bean factory.
  12.                 // 2. 重获容器
  13.                 ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
  14.                 // Prepare the bean factory for use in this context.
  15.                 // 3. 配置容器
  16.                 prepareBeanFactory(beanFactory);
  17.                 try {
  18.                         // Allows post-processing of the bean factory in context subclasses.
  19.                         // 4. 容器子类添加后处理器
  20.                         postProcessBeanFactory(beanFactory);
  21.                        
  22.                         // 标记阶段
  23.                         StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
  24.                         // Invoke factory processors registered as beans in the context.
  25.                        
  26.                         // 5. 调用BeanFactory后处理器
  27.                         invokeBeanFactoryPostProcessors(beanFactory);
  28.                         // Register bean processors that intercept bean creation.
  29.                         // 6. 注册bean后处理器
  30.                         registerBeanPostProcessors(beanFactory);
  31.                         beanPostProcess.end();
  32.                         // Initialize message source for this context.
  33.                         // 向bean工厂注册一个名为`messageSource`的单例bean
  34.                         initMessageSource();
  35.                         // Initialize event multicaster for this context.
  36.                         // 向bean工厂注册一个名为`applicationEventMulticaster`的SimpleApplicationEventMulticaster对象
  37.                         initApplicationEventMulticaster();
  38.                         // Initialize other special beans in specific context subclasses.
  39.                         // 7. tomcat初始化
  40.                         onRefresh();
  41.                         // Check for listener beans and register them.
  42.                         registerListeners();
  43.                         // Instantiate all remaining (non-lazy-init) singletons.
  44.                         finishBeanFactoryInitialization(beanFactory);
  45.                         // Last step: publish corresponding event.
  46.                         finishRefresh();
  47.                 }
  48.                 catch (RuntimeException | Error ex ) {
  49.                         if (logger.isWarnEnabled()) {
  50.                                 logger.warn("Exception encountered during context initialization - " +
  51.                                                 "cancelling refresh attempt: " + ex);
  52.                         }
  53.                         // Destroy already created singletons to avoid dangling resources.
  54.                         destroyBeans();
  55.                         // Reset 'active' flag.
  56.                         cancelRefresh(ex);
  57.                         // Propagate exception to caller.
  58.                         throw ex;
  59.                 }
  60.                 finally {
  61.                         contextRefresh.end();
  62.                 }
  63.         }
  64.         finally {
  65.                 this.startupShutdownThread = null;
  66.                 this.startupShutdownLock.unlock();
  67.         }
  68. }
复制代码
1. 准备革新

  1. protected void prepareRefresh() {
  2.         // Switch to active.
  3.         this.startupDate = System.currentTimeMillis(); // startupDate的类型是`long`,标记容器启动时刻
  4.         this.closed.set(false); // close的类型是`AtomicBoolean`,标记当前容器是否已就绪
  5.         this.active.set(true); // active的类型是`AtomicBoolean`,标记当前容器是否活跃
  6.         // 源码此处有log
  7.         // Initialize any placeholder property sources in the context environment.
  8.         // 初始化名称为`servletContextInitParams`的ServletContextPropertySource`,即初始化Servlet相关属性
  9.         initPropertySources();
  10.         // Validate that all properties marked as required are resolvable:
  11.         // see ConfigurablePropertyResolver#setRequiredProperties
  12.         getEnvironment().validateRequiredProperties();
  13.         // Store pre-refresh ApplicationListeners...
  14.         // earlyApplicationListeners 刷新容器之前已存在的监听器
  15.         if (this.earlyApplicationListeners == null) {
  16.                 this.earlyApplicationListeners = new LinkedHashSet<>(this.applicationListeners);
  17.         }
  18.         else {
  19.                 // Reset local application listeners to pre-refresh state.
  20.                 this.applicationListeners.clear();
  21.                 this.applicationListeners.addAll(this.earlyApplicationListeners);
  22.         }
  23.         // Allow for the collection of early ApplicationEvents,
  24.         // to be published once the multicaster is available...
  25.         this.earlyApplicationEvents = new LinkedHashSet<>();
  26. }
复制代码
2. 重获容器

  1. protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
  2.         refreshBeanFactory();
  3.         // 当前applicationContext是容器对象,但是包含了环境配置,事件发布器等等。而`getBeanFactory`返回的容器仅仅处理对象
  4.         return getBeanFactory();
  5. }
复制代码
  1. // GenericApplicationContext#refreshBeanFactory
  2. protected final void refreshBeanFactory() throws IllegalStateException {
  3.         // refreshed的类型是`AtomicBoolean`,代表容器正在刷新,cas表示容器只能刷新一次
  4.         if (!this.refreshed.compareAndSet(false, true)) {
  5.                 throw new IllegalStateException(
  6.                                 "GenericApplicationContext does not support multiple refresh attempts: just call 'refresh' once");
  7.         }
  8.         // 容器的id是`application`
  9.         this.beanFactory.setSerializationId(getId());
  10. }
复制代码
3. 设置容器

  1. protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
  2.         // Tell the internal bean factory to use the context's class loader etc.
  3.         // 设置bean的类加载器,是`AppClassLoader`
  4.         beanFactory.setBeanClassLoader(getClassLoader());
  5.         // 设置SPEL解析器
  6.         beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
  7.         // 设置属性编辑器,将字符串属性转为java对象,比如将"false"字符串转为Boolean.False。
  8.         beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));
  9.         // Configure the bean factory with context callbacks.
  10.         // 配置bean后处理器。`ignoreDependencyInterface`表示容器不解析这些接口,不将接口的实现放入容器。
  11.         //源码里是将这些接口放入`Set<Class<?>> ignoredDependencyInterfaces`。
  12.         // 这些接口统一由`ApplicationContextAwareProcessor`处理。
  13.         beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
  14.         beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
  15.         beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
  16.         beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
  17.         beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
  18.         beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
  19.         beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
  20.         beanFactory.ignoreDependencyInterface(ApplicationStartupAware.class);
  21.         // BeanFactory interface not registered as resolvable type in a plain factory.
  22.         // MessageSource registered (and found for autowiring) as a bean.
  23.         // 指定BeanFactory.class接口的容器对象是beanfactory
  24.         // 源码里就是将`BeanFactory.class`和`beanFactory`放入`Map<Class<?>, Object> resolvableDependencies`。
  25.         beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
  26.         beanFactory.registerResolvableDependency(ResourceLoader.class, this);
  27.         beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
  28.         beanFactory.registerResolvableDependency(ApplicationContext.class, this);
  29.         // Register early post-processor for detecting inner beans as ApplicationListeners.
  30.         // 添加bean后处理器,ApplicationListenerDetector监听实现ApplicationListener接口的bean
  31.         beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));
  32.         // Detect a LoadTimeWeaver and prepare for weaving, if found.
  33.         // NativeDetector检测当前环境是否是GraalVM native镜像。
  34.         if (!NativeDetector.inNativeImage() && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
  35.                 beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
  36.                 // Set a temporary ClassLoader for type matching.
  37.                 beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
  38.         }
  39.         // Register default environment beans.
  40.         // 向容器注册名为"environment"的单例ApplicationServletEnvironment对象
  41.         if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
  42.                 beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
  43.         }
  44.         // 向容器注册名为"systemProperties"的单例Properties对象
  45.         if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
  46.                 beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
  47.         }
  48.         // 向容器注册名为"systemEnvironment"的`UnmodifiableMap`对象
  49.         if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
  50.                 beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
  51.         }
  52.         // 向容器注册名为"applicationStartup"的单例DefaultApplicationStartup对象
  53.         if (!beanFactory.containsLocalBean(APPLICATION_STARTUP_BEAN_NAME)) {
  54.                 beanFactory.registerSingleton(APPLICATION_STARTUP_BEAN_NAME, getApplicationStartup());
  55.         }
  56. }
复制代码
4. 容器子类添加后处理处罚器

ServletWebServerApplicationContext是容器实现类,它添加bean后处理处罚器。WebApplicationContextServletContextAwareProcessor是向容器添加servletContext。
  1. // org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext
  2. protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
  3.         beanFactory.addBeanPostProcessor(new WebApplicationContextServletContextAwareProcessor(this));
  4.         beanFactory.ignoreDependencyInterface(ServletContextAware.class);
  5.         registerWebApplicationScopes();
  6. }
复制代码
5. 调用BeanFactory后处理处罚器

终极调用的是PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors()方法。后处理处罚器分2种,一种是BeanDefinitionRegistryPostProcessors,处理处罚BeanDefinitionRegistry中登记的BeanDefinition。BeanDefinition是bean的界说类,是对差别泉源(Annotation注解,xml文件)的容器界说(scope, beanName)的抽象。容器根据界说类创建容器。一种是BeanFactoryPostProcessors,处理处罚容器。

先看BeanDefinitionRegistryPostProcessors。起首处理处罚PriorityOrdered接口,之后处理处罚Ordered接口,别的的末了处理处罚。

invokeBeanDefinitionRegistryPostProcessors方法让每个后处理处罚器postProcessor调用本身的postProcessBeanDefinitionRegistry方法。此中有个org.springframework.context.annotation.ConfigurationClassPostProcessor将全部@Confuguration注解类剖析成BeanDefinitionHolder。
  1. private static void invokeBeanDefinitionRegistryPostProcessors(
  2.                         Collection<? extends BeanDefinitionRegistryPostProcessor> postProcessors, BeanDefinitionRegistry registry, ApplicationStartup applicationStartup) {
  3.                 for (BeanDefinitionRegistryPostProcessor postProcessor : postProcessors) {
  4.                         StartupStep postProcessBeanDefRegistry = applicationStartup.start("spring.context.beandef-registry.post-process")
  5.                                         .tag("postProcessor", postProcessor::toString);
  6.                         postProcessor.postProcessBeanDefinitionRegistry(registry);
  7.                         postProcessBeanDefRegistry.end();
  8.                 }
  9.         }
复制代码
BeanFactoryPostProcessors也是按照优先级举行处理处罚。

处理处罚竣过后,删除缓存。
  1. @Override
  2. public void clearMetadataCache() {
  3.         super.clearMetadataCache();
  4.         this.mergedBeanDefinitionHolders.clear();
  5.         clearByTypeCache();
  6. }
复制代码

6. 注册bean后处理处罚器


registerBeanPostProcessors方法也是按照优先级注册bean后处理处罚方法。这里的注册指的是将BeanPostProcessors放入容器,即abstractBeanFactory.addBeanPostProcessors(postProcessors)。而不是实行BeanPostProcessors,由于此时还没有创建bean。

末了将后处理处罚器重新注册一遍。而且添加ApplicationListenerDetector容器后处理处罚器。

7. tomcat初始化

onfresh()是交给容器子类自界说初始化,web容器在此设置web情况而且启动tomcat。

回复

使用道具 举报

登录后关闭弹窗

登录参与点评抽奖  加入IT实名职场社区
去登录
快速回复 返回顶部 返回列表