spring ioc 启动过程

349 阅读4分钟

demo

  public static void main(String[] args) {
  // 用我们的配置文件来启动一个 ApplicationContext
  ApplicationContext context = new ClassPathXmlApplicationContext("classpath:application.xml");

 System.out.println("context 启动成功");
  // 从 context 中取出我们的 Bean,而不是用 new MessageServiceImpl() 这种方式
  MessageService messageService = context.getBean(MessageService.class);
  // 这句将输出: hello world
  System.out.println(messageService.getMessage());
  }

ioc启动核心代码

public ClassPathXmlApplicationContext(
      String[] configLocations, boolean refresh, @Nullable ApplicationContext parent)
      throws BeansException {

   super(parent);
   setConfigLocations(configLocations);
   if (refresh) {
      refresh();
   }
}
public void refresh() throws BeansException, IllegalStateException {
   synchronized (this.startupShutdownMonitor) {
      StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");

      // Prepare this context for refreshing.
      // 初始化前的准备工作,例如对系统属性或者环境变量进行准备及验证。在某些情况下项目的使用需要读取某些系统变量,那么在启动时候,就可以通过准备函数来进行参数的校验。
      prepareRefresh();

       //初始化BeanFactory,并进行XML 文件读取(如果需要的话)。 这一步之后ApplicationContext就具有BeanFactory 所提供的功能,也就是可以进行Bean的提取等基础操作了。
      // 注册也只是将这些信息都保存到了注册中心(说到底核心是一个 beanName-> beanDefinition 的 map)
      ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

      //对BeanFactory 进行各种功能填充。
      prepareBeanFactory(beanFactory);

      try {
         // 对 BeanFactory 做额外处理。默认没有实现
         postProcessBeanFactory(beanFactory);

         StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
         // 激活各种BeanFactory 处理器(调用了各种BeanFactoryPostProcessor)。其中最为关键的是 ConfigurationClassPostProcessor ,在这里完成了配置类的解析,生成的注入容器中的bean 的 BeanDefinition。
         invokeBeanFactoryPostProcessors(beanFactory);

         // 注册和创建拦截bean创建的bean处理器。BeanPostProcessor 在这一步已经完成了创建。
         registerBeanPostProcessors(beanFactory);
         
         beanPostProcess.end();

         // 为上下文初始化Message 源,即对不同语言的消息体进行国际化处理
         initMessageSource();

         // 初始化应用消息广播器,并放入"applicationEventMulticaster" bean 中
         initApplicationEventMulticaster();

         // Initialize other special beans in specific context subclasses.
         // 从方法名就可以知道,典型的模板方法(钩子方法),
         // 具体的子类可以在这里初始化一些特殊的 Bean(在初始化 singleton beans 之前)
         onRefresh();

         // Check for listener beans and register them.
         // 注册事件监听器,监听器需要实现 ApplicationListener 接口。这也不是我们的重点,
         registerListeners();

         // Instantiate all remaining (non-lazy-init) singletons.
         // 初始化所有的 singleton beans
         //(lazy-init 的除外)
         finishBeanFactoryInitialization(beanFactory);

         // Last step: publish corresponding event.
         // 最后,广播事件,ApplicationContext 初始化完成
         finishRefresh();
      }

      catch (BeansException ex) {
         if (logger.isWarnEnabled()) {
            logger.warn("Exception encountered during context initialization - " +
                  "cancelling refresh attempt: " + 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();
         contextRefresh.end();
      }
   }
}

ioc启动流程

启动代码框架

image.png

  1. 启动前准备工作
  • 设置close,active状态
  • 记录启动时间
  • 钩子函数initPropertySources
  • 初始化容器:
  • . Set<ApplicationListener<?>> earlyApplicationListeners
  • . Set<ApplicationListener<?>> applicationListeners
  • . Set earlyApplicationEvents
  1. 初始化BeanFactory
  • 2.1、解析xml,抽象BeanDefinition
  • 2.2、初始化 Map<String, BeanDefinition> beanDefinitionMap
  • 2.3、初始化 List beanDefinitionNames
  • 2.4、初始化Map<Class<?>, Object> resolvableDependencies
  1. 初始化容器组件
  • 3.1 、类加载器
  • 3.2 、spel Resolver
  • 3.3 、设置aware
  • 3.4 、注册可装配的依赖,而不是bean:BeanFactory、ResourceLoader、ApplicationEventPublisher、ApplicationContext
  • 3.5 、注册early post-processor检测bean是否为applicationlistener
  • 3.6 、注册默认的环境beans:environment
  • 3.7 、注册BeanFactoryPostProcessor
  • 3.8 、执行BeanFactoryPostProcessor
  • 3.9 、注册BeanPostProcessor
  • 3.10 、国际化
  • 3.11、执行onRefresh()钩子函数
  • 3.12、注册监听
  1. 创建实例(单实例,lazy-init 的除外)
  2. 容器启动收尾工作,广播事件,ApplicationContext 初始化完成

容器启动流程图

image.png

ClassPathXmlApplicationContext类图

image.png

bean生命周期,源码请阅读finishBeanFactoryInitialization 方法

  1. 创建BeanFactory
  2. 执行BeanDefinitionRegistryPostProcessor接口方法
  3. 执行BeanFactoryPostProcessor接口方法
  4. 调用Bean的构造方法
  5. 设置属性(set,自动注入)
  • 初始化bean begin
  1. 执行各种xxxAware方法
  2. 调用BeanPostProcessor接口的postProcessBeforeInitialization方法
  3. 执行初始化方法,分三种
  • bean中指定init-method
  • bean中实现@postConsruct
  • bean中实现了InitializingBean 接口中afterPropertiesSet方法
  1. 调用BeanPostProcessor接口的postProcessAfterInitialization方法
  • end
  1. 容器关闭时,调用DisposableBean接口的销毁方法
  2. 执行destroy-method方法

image.png

image.png

循环依赖问题

protected Object getSingleton(String beanName, boolean allowEarlyReference) {
   // Quick check for existing instance without full singleton lock
   Object singletonObject = this.singletonObjects.get(beanName);
   if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
      singletonObject = this.earlySingletonObjects.get(beanName);
      if (singletonObject == null && allowEarlyReference) {
         synchronized (this.singletonObjects) {
            // Consistent creation of early reference within full singleton lock
            singletonObject = this.singletonObjects.get(beanName);
            if (singletonObject == null) {
               singletonObject = this.earlySingletonObjects.get(beanName);
               if (singletonObject == null) {
                  ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
                  if (singletonFactory != null) {
                     singletonObject = singletonFactory.getObject();
                     this.earlySingletonObjects.put(beanName, singletonObject);
                     this.singletonFactories.remove(beanName);
                  }
               }
            }
         }
      }
   }
   return singletonObject;
}

ApplicationContext注入问题

spring发布订阅模式

  • org.springframework.context.event.SimpleApplicationEventMulticaster#multicastEvent(org.springframework.context.ApplicationEvent, org.springframework.core.ResolvableType)
public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {
   ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
   Executor executor = getTaskExecutor();
   for (ApplicationListener<?> listener : getApplicationListeners(event, type)) {
      if (executor != null) {
         executor.execute(() -> invokeListener(listener, event));
      }
      else {
         invokeListener(listener, event);
      }
   }
}
  • 同步
  • 异步

## LifecycleProcessor接口

  • 在Spring中提供了Lifecle接口,Lifecycle 中包含start/stop方法,实现此接口后Spring会保证在启动的时候调用其start方法开始生命周期,并在Spring关闭的时候调用 stop方法来结束生命周期
public interface Lifecycle { 
void start(); 
void stop(); 
boolean isRunning(); 
}
  • 当ApplicationContext自身启动和停止时,它将自动调用上下文内所有生命周期的实现。通过委托给LifecycleProcessor来做这个工作。注LifecycleProcessor继承了Lifecycle接口。它也增加了两个其他的方法来与上下文交互,使得可以刷新和关闭。
public interface LifecycleProcessor extends Lifecycle { 
void onRefresh(); 
void onClose(); 
}

  • 那为什么要用LifecycleProcessor 把Lifecycle包装一遍呢?
  1. 因为Lifecycle的start(), stop()方法都要手动调用,而LifecycleProcessor提供了回调方法供开关ApplicationContext时自动调用。
  2. 多个Lifecycle的调用是有一定的顺序要求的,比如一个类依赖于另一个类,那么另一个类就要先执行。而LifecycleProcessor恰好提供了getPhase()来控制开关的顺序。

spring 设计模式