一马平川
不积跬步无以至千里,后继才能薄发

SpringIOC源码学习笔记

2021年05月03日
0
未分类

趁着五一假期深入学习一下SpringIOC构建的源码,获益匪浅~

ApplicationContext

IOC容器是基于 应用上下文类 的子类,因为这个类继承了 ListableBeanFactory 可列表BeanFactory和 HierarchicalBeanFactory 分层BeanFactory ,这两个类继承于 BeanFactory ,然后通过组合的方式把 AutowireCapableBeanFactory 组合进去了,用来支撑DI功能。

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
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// 刷新上下文准备:记录开始时间,设置运行标识
prepareRefresh();

// 销毁旧BeanFactory,新建一个新的BeanFactory,并把配置中的bean转化为BeanDefinition
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

// 设置 BeanFactory 的类加载器,添加几个 BeanPostProcessor,手动注册几个特殊的 bean
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();

// 实例化单例bean(非懒加载)
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();
}
}
}

关键方法 refresh()

  1. 给方法上锁,避免在刷新上下文期间重复调用
  2. 销毁旧BeanFactory,新建一个新的BeanFactory,并把配置中的bean转化为BeanDefinition
    1. 读取xml中的配置的 <bean /> 标签配置转换为 BeanDefinition 然后把 BeanDefinition 注册到注册中心,并发送注册事件。
    2. 说到底核心是一个 beanName-> beanDefinition 的 map
  3. 设置BeanFactory的类加载器,手动注册几个特殊类,注册BeanPostProcessor
  4. 回调BeanFactoryPost类
  5. 实例化非懒加载的单例Bean finishBeanFactoryInitialization(beanFactory);
    1. 手动加载 conversionService 用于类型转换,如controller中入参的转换
    2. preInstantiateSingletons() :初始化/预初始化单例bean
      1. 获取所有beanDefinition的在map中的name
      2. 分别加载 FactoryBean 和普通单例bean,分别调用 AbstractBeanFactorygetBean() 方法进行初始化 :
        1. 传入的beanName在别名map中找直到找到正式名称
        2. 获取已经创建完成的缓存了的对象,通过正式名称查询是否已经创建完成或者正在创建,如果正在创建在 earlySingletonObjects 早期单例map缓存中获取,如果没有则创建一个早期对象,并add进 earlySingletonObjects 。如果找到了这个对象,则直接返回这个对象,不需要再创建了
        3. 获取当前单例对象的 beanDefinition ,如果在当前上下文找不到,就到父容器中找 :找不到这个单例对象,说明还没有初始化,现在开始初始化
        4. 合并拥有父子关系的 bean 对应的 beanDefinition
        5. 检查 beandependsOn 属性,避免在这里循环依赖,并把依赖到的 bean 先初始化
        6. 通过自定义的 ObjectFactory 进行创建单例实例,如果是 FactoryBean 还需要多做一步通过这个工厂类创建对应的单例实例 , 核心方法 AbstractAutowireCapableBeanFactorycreateBean(beanName, mbd, args);
          1. 判断是否需要方法重写,如定义了 lookup-methodreplace-method ,需要经过CGLIB生成新的类

          2. 判断是否有代理类需要对 bean 进行增强 InstantiationAwareBeanPostProcessor

            1
            Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
          3. bean 进行创建 doCreateBean(beanName, mbdToUse, args)

            1. 判断是否是 FactoryBean ,如果不是就实例化 bean ,如果是,则通过这个工厂类创建对应的单例

              1
              instanceWrapper = createBeanInstance(beanName, mbd, args);
              1. 确保已经加载了此 class
              2. 校验一下这个类的访问权限
              3. 看下是否配置了 factory-method ,如果有则采用工厂方法实例化
              4. 判断是用 无参构造 还是 构造函数依赖注入 ,使用对应的构造方法
            2. 解决循环依赖问题

            3. 装配成员变量 populateBean(beanName, mbd, instanceWrapper);

              1. 区分通过名称还是类型进行注入:
                1. 通过名字找到所有属性值,如果是 bean 依赖,先初始化依赖的 bean。记录依赖关系
                2. 通过类型装配。复杂一些
              2. 对采用 @Autowired、@Value 注解的依赖进行设值到 PropertyValues
              3. 通过配置好的 PropertyValues 对象对 bean 进行设值
            4. 初始化 beaninitializeBean(beanName, exposedObject, mbd);

              1. 如果 bean 实现了 BeanNameAwareBeanClassLoaderAwareBeanFactoryAware 接口,回调
              2. BeanPostProcessorpostProcessBeforeInitialization() 回调
              3. 处理 bean 中定义的 init-method ,或者如果 bean 实现了 InitializingBean 接口,调用 afterPropertiesSet() 方法
              4. BeanPostProcessorpostProcessAfterInitialization 回调,aop在这里做增强

如果喜欢这篇文章,可以给作者评个份哦~

原文声明: "转载本站文章请注明作者和出处Nothinglin ,请勿用于任何商业用途"

公众号:苦逼的学生仔