文章目录
1 处理名称,检查缓存
要点:
- 掌握别名处理
- 了解FactoryBean的名字规范
- 掌握三级缓存的概念
总结:
- 先把别名解析为实际名称,再进行后续处理
- 若要FactoryBean本身,需要使用 & 名称获取
- singletonObjects是一级缓存
- singletonFactories是三级缓存,放单例工厂
- earlySingletonObjects是二级缓存,放单例工厂的产品,可称为提前单例对象
2 处理父子容器
要点:
- 了解有父容器时的查找规则
总结:
- 父子容器的bean名称可以重复
- 优先找子容器的bean,找到了直接返回,找不到继续到父容器中找
3 处理 dependsOn
- 如果当前 bean 有通过 dependsOn 指定了非显式依赖的 bean,这一步会提前创建这些 dependsOn 的 bean
- 所谓非显式依赖,就是指两个 bean 之间不存在直接依赖关系,但需要控制它们的创建先后顺序
4 按 Scope 创建 bean
要点:
- 理解三种scope
总结: - scope理解为从xxx范围内找个 bean 更加贴切
- singleton scope 表示从单例池范围内获取bean,如果没有,则创建并放入单例池
- 对于自定义 scope,例如 request,首先到 request 域获取 bean,如果有则直接返回,没有再进入创建流程
5 创建 bean
5.1 创建 bean 实例
要点 | 总结 |
---|---|
有自定义 TargetSource 的情况 | 由 AnnotationAwareAspectJAutoProxyCreator 创建代理返回 |
Supplier 方式创建 bean 实例 | 为 Spring 5.0 新增功能,方便编程方式创建 bean 实例 |
FactoryMethod 方式 创建 bean 实例 | ① 分成静态工厂与实例工厂;② 工厂方法若有参数,需要对工厂方法参数进行解析,利用 resolveDependency;③ 如果有多个工厂方法候选者,还要进一步按权重筛选 |
AutowiredAnnotationBeanPostProcessor | ① 优先选择带 @Autowired 注解的构造;② 若有唯一的带参构造,也会入选 |
mbd.getPreferredConstructors | 选择所有公共构造,这些构造之间按权重筛选 |
采用默认构造 | 如果上面的后处理器和 BeanDefiniation 都没找到构造,采用默认构造,即使是私有的 |
5.2 创建 bean - 依赖注入
要点 | 总结 |
---|---|
AutowiredAnnotationBeanPostProcessor | 识别 @Autowired 及 @Value 标注的成员,封装为 InjectionMetadata 进行依赖注入 |
CommonAnnotationBeanPostProcessor | 识别 @Resource 标注的成员,封装为 InjectionMetadata 进行依赖注入 |
resolveDependency | 用来查找要装配的值,可以识别:① Optional;② ObjectFactory 及 ObjectProvider;③ @Lazy 注解;④ @Value 注解(${ }, #{ }, 类型转换);⑤ 集合类型(Collection,Map,数组等);⑥ 泛型和 @Qualifier(用来区分类型歧义);⑦ primary 及名字匹配(用来区分类型歧义) |
AUTOWIRE_BY_NAME | 根据成员名字找 bean 对象,修改 mbd 的 propertyValues,不会考虑简单类型的成员 |
AUTOWIRE_BY_TYPE | 根据成员类型执行 resolveDependency 找到依赖注入的值,修改 mbd 的 propertyValues |
applyPropertyValues | 根据 mbd 的 propertyValues 进行依赖注入(即xml中 `<property name ref |
5.3 创建 bean - 初始化
要点 | 总结 |
---|---|
内置 Aware 接口的装配 | 包括 BeanNameAware,BeanFactoryAware 等 |
扩展 Aware 接口的装配 | 由 ApplicationContextAwareProcessor 解析,执行时机在 postProcessBeforeInitialization |
@PostConstruct | 由 CommonAnnotationBeanPostProcessor 解析,执行时机在 postProcessBeforeInitialization |
InitializingBean | 通过接口回调执行初始化 |
initMethod | 根据 BeanDefinition 得到的初始化方法执行初始化,即 <bean init-method> 或 @Bean(initMethod) |
创建 aop 代理 | 由 AnnotationAwareAspectJAutoProxyCreator 创建,执行时机在 postProcessAfterInitialization |
5.4 创建 bean - 注册可销毁 bean
要点:
- 判断并登记可销毁bean
总结:
- 判断依据
- 如果实现了 DisposableBean 或 AutoCloseable 接口,则为可销毁 bean
- 如果自定义了 destroyMethod,则为可销毁 bean
- 如果采用 @Bean 没有指定 destroyMethod,则采用自动推断方式获取销毁方法名(close,shutdown)
- 如果有 @PreDestroy 标注的方法
- 存储位置
- singleton scope 的可销毁 bean 会存储于 beanFactory 的成员当中
- 自定义 scope 的可销毁 bean 会存储于对应的域对象当中
- prototype scope 不会存储,需要自己找到此对象销毁
- 存储时都会封装为 DisposableBeanAdapter 类型对销毁方法的调用进行适配
6. 类型转换处理
- 如果 getBean 的 requiredType 参数与实际得到的对象类型不同,会尝试进行类型转换
7. 销毁 bean
- 销毁时机
- singleton bean 的销毁在 ApplicationContext.close 时,此时会找到所有 DisposableBean 的名字,逐一销毁
- 自定义 scope bean 的销毁在作用域对象生命周期结束时
- prototype bean 的销毁可以通过自己手动调用 AutowireCapableBeanFactory.destroyBean 方法执行销毁
- 同一 bean 中不同形式销毁方法的调用次序
- 优先后处理器销毁,即 @PreDestroy
- 其次 DisposableBean 接口销毁
- 最后 destroyMethod 销毁(包括自定义名称,推断名称,AutoCloseable 接口 多选一)