一、概述

IoC:控制反转(Inversion of Control)容器,是一种设计思想。在 Java 开发中,IoC 意味着将定义好的对象交给容器管理,而不是交给自己控制。

DI:依赖注入(Dependency Injection):组件之间的以来关系由容器在运行时期决定,即由容器动态的将某个依赖关系注入到组件之中。

二、Bean 的创建

2.1 IoC 容器的初始化

2.1.1 Spring IoC 的初始化主要有四个步骤:

  1. Bean 定义的定位,包括 xml 中,或者一个注解,或者文件其他形式。这些都被用Resource来定位,读取Resource获取BeanDefinition 注册到 Bean定义注册表中。
  2. 第一次向容器getBean操作会触发Bean的创建过程,实列化一个Bean时 ,根据BeanDefinition中类信息等实列化Bean.
  3. 将实列化的Bean放到单列Bean缓存内。
  4. 此后再次获取向容器getBean就会从缓存中获取。

2.1.2核心方法 refresh() :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
@Override
public void refresh() throws BeansException, IllegalStateException {
  synchronized (this.startupShutdownMonitor) {
    StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");

    // 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);

      StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
      // Invoke factory processors registered as beans in the context.
      invokeBeanFactoryPostProcessors(beanFactory);

      // Register bean processors that intercept bean creation.
      registerBeanPostProcessors(beanFactory);
      beanPostProcess.end();

      // 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) {
      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();
    }
  }
}

1.prepareRefresh 准备刷新

  • 设置启动时间,设计容器激活标志(active=true);
  • 初始化 properties 资源,比如一些属性的占位符(@Value注解等);
  • 验证必须存在的properties(validateRequiredProperties);
  • 初始earlyApplicationEnvents.用于收集已经产生的ApplicationEnvents.

2.obtainFreshBeanFactory 获取容器

  • 调用子类的refeshBeanFactory(), SpringBoot中采用默认的实现,设置BeanFactory的SerializationId,设置refreshed标志为true。
  • 获取BeanFactory;
  • XmlWebApplicationContext ,AnnotationConfigApplicationContext 会在这一步加载BeanDefinition

3.prepareBeanFactory 为了接下来使用BeanFactory 做准备

  • 为内部的BeanFactory设置类加载器
  • 设置表达式解析器,属性编辑器。
  • 注册:BeanPostProcessor(ApplicationContextAwareProcessor,ApplicationListenerDetector)
    • ApplicationContextAwareProcessor:对Spring 中各种Aware接口的支持,在初始化Bean前,调用Bean实现的Aware接口方法。
    • ApplicationListenerDetector:用于收集实现了ApplicationListener接口的Bean
  • 注册指定的依赖类型和对应的value
    • 例如: beanFactory.registerResolvableDependency(ResourceLoader.class, this); 那么在类中自动注入ResourceLoader类型的对象,就会拿到当前IOC容器。
    • 例如:这里的 ApplicationContext 也会拿到 IoC 容器。
  • 注入一些其它信息的bean,比如environment、systemProperties等

4.postProcessBeanFactory 后处理BeanFactory

用于在BeanFactory 完成标准的初始化之后修改BeanFactory。不同容器根据自己的需求添加特殊的后置处理器;

EmbeddedWebApplicationContext 容器在这里添加了对 ServletContextAware支持的 Bean 后置处理器(WebApplicationContextServletContextAwareProcessor)。(而ClassPathXml和AnnotationConfig都没有后置处理器)

BeanFactoryPostProcessor是spring对外提供的接口,用来拓展spring,能够在spring容器加载了所有bean的信息之后、bean实例化之前执行,修改bean的定义属性。常用场景包括spring中占位符的处理、我们自定义的敏感信息的解密处理。

5.postProcessBeanFactory 后处理BeanFactory

实例化并且执行所有已经注册到BeanFactory中的 BeanFactoryPostProcessor。支持按照Order排序。

  • 调用PostProcessorRegistrationDelegate的静态方法invokeBeanFactoryPostProcessors,执行顺序如下:

1.执行ApplicationContext初始化器注册的BeanDefinitionRegistryPostProcessor类型的处理器

2.执行实现了PriorityOrdered接口的BeanDefinitionRegistryPostProcessor。

3.执行实现了Ordered的BeanDefinitionRegistryPostProcessor

4.执行所有后置处理器的 BeanFactoryPostProcessor 的接口方法

5.获取所有的BeanFactoryPostProcessor,排除已经执行过得后置处理器。

6.按照2-4的顺序 执行所有未执行的BeanFactoryPostProcessor。

  • BeanFactoryPostProcessor 接口

针对BeanFactory 的处理,允许使用者修改容器中的bean definitions,例如:ServletComponentRegisteringPostProcessor提供对@WebFilter,@WebServlet,@WebListener注解的扫描,并注册到容器中。ConfigurationClassPostProcessor 对所有的@Configuration类进行动态代理的增强。注意使用时不能对任何BeanDefinition 进行实列化操作

  • BeanDefinitionRegistryPostProcessor 接口

如图,继承自BeanFactoryPostProcessor,针对BeanDefinitionRegistry的后置处理器,会先于BeanFactoryPostProcessor 执行。

同时,ConfigurationClassPostProcessor后置处理器实现了 PriorityOrdered 与 BeanDefinitionRegistryPostProcessor接口,优先级最高的后置处理器,在SpringBoot自动配置的实现中起到举足轻重的作用。对@Configuration,@Bean,@ComponentScan,@Import,@ImportResource,@PropertySource注解解析。

image-20220614115453886

6.registerBeanPostProcessors 注册bean后置处理器

  1. 委托给PostProcessorRegistrationDelegate的静态方法registerBeanPostProcessors执行

  2. BeanPostProcessors 接口,该接口在Bean的实例化过程中被调用,在对一个对象进行初始化前后被调用。

    实现了 EnvironmentAware,EmbeddedValueResolverAware,ResourceLoaderAware,ApplicationContextAware等Aware就是这个时候 被执行的。

  3. MergedBeanDefinitionPostProcessor 接口,该接口继承了BeanPostProcessors接口, 会在 bean 实列化 之后 属性注入前 执行。例如 对@Autowired @Resource @Value 注解的解析。

image-20220614121315900

7.initMessageSource 和 initApplicationEventMulticaster

在Spring容器中初始化一些国际化相关的属性;在容器中初始化Application事件广播器。

8.onRefresh

onRefresh是一个模板方法,留给子类容器扩赞,不同的容器做不同的事情。

例如:容器AnnotationConfigEmbeddedWebApplicationContext中会调用createEmbeddedServletContainer方法去创建内置的Servlet容器。 EmbeddedServletContainerAutoConfiguration 类中定义了 Spring boot 支持的三种 Servlet容器。Tomcat, Jetty 和 Undertow。

9.registerListeners

​ 将所有的 ApplicationListener 实现类注册 到 ApplicationEventMulticaster中,觉得是观察者模式。

10.finishBeanFactoryInitialization

实列化所有 非懒加载的 类。

11.finishRefresh

  1. 完成容器的初始化过程,发布相应事件。
  2. 发布 ContextRefreshedEvent事件。
  3. 发布容器启动事件。

2.2 Bean的注入方式

常用的注入方式:SET注入,构造器注入,静态工厂,实例工厂,注解方式

具体参考 Bean注入方式详解

三、Bean 生命周期以及创建过程

3.1 Bean 生命周期

如图,总的来说可以包括四个部分:实例化 ——–> 属性赋值 ——–> 初始化 ——–> 销毁。

img

3.2 Bean 实例化流程

对应源码:AbstactApplicationContext.finishBeanFactoryInitialization —-> DefaultListenableBeanFactory.preInstantiateSingletons —-> AbstractBeanFactory.doGetBean

  1. 遍历所有被加载到缓存中的 beanName,触发所有剩余的非懒加载单例 bean 的实例化。
  2. 首先通过 beanName 尝试从缓存中获取,如果存在则跳过实例化过程;否则,进行 bean 的实例化。

image-20220614133152496

  1. 根据 BeanDefinition,BeanFactory 使用反射通过构造函数创建 bean 实例。

    注意:此时的 BeanFactory 在容器的初始化阶段第 6 步注册了BeanPostProcessor,用在Bean 的初始化阶段

  2. 根据 BeanDefinition,进行 bean 实例属性填充。

  3. 执行 bean 实例的初始化。

    5.1 触发 Aware 方法。

    5.2 触发 BeanPostProcessor 的 postProcessBeforeInitialization 方法。

    5.3 如果 bean 实现了 InitializingBean 接口,则触发 afterPropertiesSet() 方法。

    5.4 如果 bean 设置了 init-method 属性,则触发 init-method 指定的方法。

    5.5 触发 BeanPostProcessor 的 postProcessAfterInitialization 方法。

  4. 将创建好的 bean 实例放到缓存中,用于之后使用。