【Spring容器启动流程是怎样的】

  • Spring容器的启动流程可以归纳为三个步骤:

    1.初始化Spring容器,也就是启动Spring时,注册Spring内置的BeanPostProcessor的BeanDefinition到容器中。

    • spring容器的初始化时,通过this()调用了无参构造函数,主要做了以下三个事情:
      1. 实例化BeanFactory工厂【DefaultListableBeanFactory】,用于生成Bean对象
      2. 实例化BeanDefinitionReader注解配置读取器,用于对特定注解(如@Service、@Repository)的类进行读取,并转化成 BeanDefinition对象,(BeanDefinition是Spring中极其重要的一个概念,它存储了bean对象的所有特征信息,如是否单例,是否懒加载,factoryBeanName等)
      3. 实例化ClassPathBeanDefinitionScanner路径扫描器,用于对指定的包目录进行扫描查找 bean 对象

    2.将配置类的BeanDefinition注册到容器中。

    • 主要是用来解析用户传入的SpringConfig配置类解析成一个 BeanDefinition 然后注册到容器中

    3.调用refresh()方法刷新容器

    • refresh()主要用于容器的刷新,Spring中的每一个容器都会调用refresh()方法进行刷新,无论是Spring的父子容器,还是Spring Cloud Feign中的feig 隔离容器,每一个容器都会调用这个方法完成初始化。refresh()可划分为12个步骤。
/*因为是基于java-config技术分析源码,所以这里的入口是AnnotationConfigApplicationContext。如果是使用xml分析,那么入口即为 ClassPathXmlApplicationContext。它们俩的共同特征便是都继承AbstractApplicationContext类,而大名鼎鼎的refresh()便是在这个类中定义的。我们接着分析AnnotationConfigApplicationContext类,源码如下:*/
// 初始化容器
public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) {
    // 1.注册Spring内置的后置处理器的BeanDefinition到容器
    this();
    // 2.注册配置类BeanDefinition到容器
    register(annotatedClasses);
    // 3.加载或者刷新容器中的Bean
    refresh();
}

//this()的源码:
public AnnotationConfigApplicationContext() {
    StartupStep createAnnotatedBeanDefReader = this.getApplicationStartup().start("spring.context.annotated-bean-reader.create");
    this.reader = new AnnotatedBeanDefinitionReader(this);
    createAnnotatedBeanDefReader.end();
    this.scanner = new ClassPathBeanDefinitionScanner(this);
}

//register(annotatedClasses)的简略源码:
@Override
public void register(Class<?>... componentClasses) {
    Assert.notEmpty(componentClasses, "At least one component class must be specified");
    StartupStep registerComponentClass = this.getApplicationStartup().start("spring.context.component-classes.register").tag("classes", () -> Arrays.toString(componentClasses));
    this.reader.register(componentClasses);
    registerComponentClass.end();
}

//refresh()的简略源码:
public void refresh() throws BeansException, IllegalStateException {
	synchronized (this.startupShutdownMonitor) {
		// 1. 刷新前的预处理
		prepareRefresh();
		// 2. 获取 beanFactory,即前面创建的【DefaultListableBeanFactory】
		ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
		// 3. 预处理 beanFactory,向容器中添加一些组件
		prepareBeanFactory(beanFactory);
		try {
			// 4. 子类通过重写这个方法可以在 BeanFactory 创建并与准备完成以后做进一步的设置
			postProcessBeanFactory(beanFactory);
			// 5. 执行 BeanFactoryPostProcessor 方法,beanFactory 后置处理器
			invokeBeanFactoryPostProcessors(beanFactory);
			// 6. 注册 BeanPostProcessors,bean 后置处理器
			registerBeanPostProcessors(beanFactory);
			// 7. 初始化 MessageSource 组件(做国际化功能;消息绑定,消息解析)
			initMessageSource();
			// 8. 初始化事件派发器,在注册监听器时会用到
			initApplicationEventMulticaster();
			// 9. 留给子容器(子类),子类重写这个方法,在容器刷新的时候可以自定义逻辑,web 场景下会使用
			onRefresh();
			// 10. 注册监听器,派发之前步骤产生的一些事件(可能没有)
			registerListeners();
			// 11. 初始化所有的非单实例 bean
			finishBeanFactoryInitialization(beanFactory);
			// 12. 发布容器刷新完成事件
			finishRefresh();
		}
		catch(){...}
        finally{...}
	}
}

你可能感兴趣的:(spring,java,后端)