Spring源码系列:BeanFactory的创建
2019独角兽企业重金招聘Python工程师标准>>>
Spring的Ioc容器其实就是一个bean的关系网,依赖于core,bean,context三个组件来构建的。在spring中最核心的就是对于bean的管理。而bean又依托于我们的容器。本文将从顶层分析一下spring中beanFactory的具体创建过程,为后续的bean的生命周期提供一个基础。 BeanFactory的继承体系
从上图可以看到,BeanFactory有三个子类:ListableBeanFactory
HierarchicalBeanFactory
AutowireCapableBeanFactory
(上述三个类的子类体系小伙伴们可以自己对着源码看下,实在太多)
看下上图中最底层的DefaultListableBeanFactory类的定义:
public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable
这个其实就是BeanFactory的默认实现类,它直接或者间接的实现了所有的接口。其实在看spring源码的时候都会遇到类似的设计模式,对于某一个具体的功能,通常都会定义很多层的接口,层层包装,层层委托。这种做法的好处就是,对于不同的场合都会有特定的接口;这样一来就可以在spring内部对对象的传递和转化操作都会有一些访问限制。 例如ListableBeanFactory接口表示这些Bean是可列表的,而HierarchicalBeanFactory表示的是这些Bean是有继承关系的,也就是每个Bean有可能有父Bean。AutowireCapableBeanFactory接口定义Bean的自动装配规则。这四个接口共同定义了Bean的集合、Bean之间的关系、以及Bean行为。
BeanFactory的创建
在之前的文章中说过了容器的刷新过程。BeanFactory的创建也在wac.refresh()方法中。具体看下到底是通过哪些子类来完成的:
// 通知子类刷新内部的bean工厂。 ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
1.AbstractApplicationContext中的obtainFreshBeanFactory
下面是obtainFreshBeanFactory的方法逻辑:
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() { //这个是具体创建的方法,由子类实现 refreshBeanFactory(); //获取BeanFactory实例对象(ConfigurableListableBeanFactory类型的) ConfigurableListableBeanFactory beanFactory = getBeanFactory(); if (logger.isDebugEnabled()) { logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory); } return beanFactory; }
refreshBeanFactory并未有具体的实现逻辑,这个方法主要是通过委托给子类的refreshBeanFactory方法来实现,在AbstractApplicationContext中refreshBeanFactory是一个抽象模板方法:
protected abstract void refreshBeanFactory() throws BeansException, IllegalStateException;
2.refreshBeanFactory方法(AbstractRefreshableApplicationContext类中):
下面只注释与beanFactory创建相关的代码
protected final void refreshBeanFactory() throws BeansException { //是否已经有BeanFactory了 if (hasBeanFactory()) { //销毁原有的Bean destroyBeans(); //关闭工厂 closeBeanFactory(); } try { //创建一个新的beanFactory DefaultListableBeanFactory beanFactory = createBeanFactory(); beanFactory.setSerializationId(getId()); customizeBeanFactory(beanFactory); loadBeanDefinitions(beanFactory); synchronized (this.beanFactoryMonitor) { this.beanFactory = beanFactory; } } catch (IOException ex) { throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex); } }
这个方法是实现执行这个上下文的底层bean工厂的实际刷新,如果有的话之前有BeanFactory存在,则关闭以前的bean工厂。并为上下文生命周期的下一个阶段初始化一个新鲜的bean工厂。
3.createBeanFactory(AbstractRefreshableApplicationContext类中)
protected DefaultListableBeanFactory createBeanFactory() { return new DefaultListableBeanFactory(getInternalParentBeanFactory()); }
这个方法就是为当前上下文创建一个内部的bean工厂。每次调用refresh()方法是都会创建尝试创建。默认实现是创建一个DefaultListableBeanFactory。并通过getInternalParentBeanFactory()获取内部bean工厂来作为父级bean工厂。可以在子类中重写,例如自定义DefaultListableBeanFactory的设置。
getInternalParentBeanFactory(AbstractApplicationContext类中)
protected BeanFactory getInternalParentBeanFactory() { return (getParent() instanceof ConfigurableApplicationContext) ? ((ConfigurableApplicationContext) getParent()).getBeanFactory() : getParent(); }
4.DefaultListableBeanFactory的构造函数
/**
* 通过给定的父类创建一个新的DefaultListableBeanFactory容器
* @param parentBeanFactory the parent BeanFactory
*/
public DefaultListableBeanFactory(BeanFactory parentBeanFactory) { super(parentBeanFactory);
}
super(parentBeanFactory)调用的是AbstractAutowireCapableBeanFactory的构造函数
/**
* 通过给定的父类构建新的AbstractAutowireCapableBeanFactory
* @param parentBeanFactory parent bean factory, or {@code null} if none
*/
public AbstractAutowireCapableBeanFactory(BeanFactory parentBeanFactory) {
this();
//设置父工厂
setParentBeanFactory(parentBeanFactory);
}
this(),还是AbstractAutowireCapableBeanFactory的构造函数:
/**
* 构建一个新的AbstractAutowireCapableBeanFactory.
*/
public AbstractAutowireCapableBeanFactory() {
super();
ignoreDependencyInterface(BeanNameAware.class);
ignoreDependencyInterface(BeanFactoryAware.class);
ignoreDependencyInterface(BeanClassLoaderAware.class);
}
super() ; AbstractBeanFactory的构造函数
/**
* 构建一个新的AbstractBeanFactory.
*/
public AbstractBeanFactory() {
}
转载于:https://my.oschina.net/u/3959468/blog/2052399
Spring源码系列:BeanFactory的创建相关推荐
- Spring源码系列(十二)Spring创建Bean的过程(二)
1.写在前面 上篇博客主要Spring在创建Bean的时候,第一次调用的Bean的后置处理器的过程,同时笔者也打算将整个Spring创建的Bean的过程,通过这个系列,将Bean的创建过程给讲清楚,废 ...
- Spring源码系列:依赖注入(二)createBean
在Spring源码系列:依赖注入(一)(AbstractBeanFactory-getBean)最后说道getBean是依赖注入的起点,bean的创建都是通过createBean来完成具体的创建的.c ...
- Ioc容器beanDefinition-Spring 源码系列(1)
Ioc容器beanDefinition-Spring 源码系列(1) 目录: Ioc容器beanDefinition-Spring 源码(1) Ioc容器依赖注入-Spring 源码(2) Ioc容器 ...
- Spring源码系列- Spring Beans - 核心类的基本介绍
Spring源码系列- Spring Beans - 核心类的基本介绍 读过上一篇文章的读者应该都能对Spring的体系结构有一个大致的了解,在结尾处,我也说过会从spring-beans包开始分析, ...
- 【spring源码系列-05】refresh中prepareRefresh方法的执行流程
Spring源码系列整体栏目 内容 链接地址 [一]spring源码整体概述 https://blog.csdn.net/zhenghuishengq/article/details/13094088 ...
- Spring源码系列:BeanDefinition载入(下)
在Spring源码系列:BeanDefinition载入(上)中已经大概捋了一下解析过程,本篇将记录一下bean的注册过程. bean的注册就是DefaultListableBeanFactory中r ...
- Spring源码系列-第1章-Spring源码纵览【持续更新中】
文章目录 必读 第1章-Spring源码纵览 概述 简单的继承关系图 Spring框架整体流程 核心组件接口分析 Resource资源 方法 实现类 ResourceLoader资源加载器 方法 实现 ...
- Spring源码系列(十三)——Spring源码编译及详细注解
文章目录 1. 环境搭建 2. 代码编译 2.1 编译代码 2.1.1 build.gradle 2.1.1.1 第一处 2.1.1.2 第二处 2.1.2 gradle.properties 2.1 ...
- spring源码系列一--BeanDefinition
如果说java是由对象组成,那么spring-framework框架可以说是由BeanDefinition所构成.BeanDefinitiion其实是spring中的顶级接口,我们在阅读源码之前必须要 ...
最新文章
- android+busybox+编译,Android版busybox编译
- tp5 保存图片背景黑色_少女心背景图 | 风环绕世界百圈,不如见你时心动
- vc编程的ime输入法菜单开发
- c语言一本书的页码从自然数1开始顺序编码,C++_关于统计数字问题的算法,一本书的页码从自然数1开始顺 - phpStudy...
- 如何在线下载哔哩哔哩上的视频
- 外贸大宗商品行业ERP管理解决方案
- 企业信用代码等常用的正则验证
- python 安卓王者荣耀刷金币
- Linux scp和sftp
- IMTOKEN 2.9.9官网1:1双端,用户管理系统,后台可查询用户使用情况
- 基于JPEG压缩编码的数据压缩算法的研究与实现(转)
- 数字证书及公钥、私钥
- 一天到晚只会抱怨的人必定是不成熟的人
- 蓝桥杯 — IAP15F2K61S2-89C52 转换板说明文件
- 生存曲线 p值 python_超详细讲解生信SCI中的生存曲线作图,不看后悔系列
- 深入解析 DataGrid 过滤功能
- Nor Flash笔记--看一图看懂并学会计算Flash大小
- 联想微型计算机C200配置,联想C200一体电脑基本配置
- 公务员碑文辞职书走红,以教堂碑文为铭改变生活
- win10taskkill强行结束进程_批处理文件BAT找到进程PID并强制结束TaskKill进程
热门文章
- c++ 纯虚函数导出
- 1019. 链表中的下一个更大节点
- Linux日常运维管理技巧(三)iptables规则备份和恢复、firewalld的9个zone、任务计划cron、chkconfig系统服务管理、添加服务命令、systemctl管理服务
- Shell通过过滤条件(比如IP)分类流量包,最后合并流量包
- ROS kinetic外接Realsense D435i跑ORB_SLAM2教程
- 对HashMap对象的键值对内容进行排序
- 如何解决comctl32.dll文件丢失的问题?
- 支付宝支付系统繁忙,请稍后再试(ALI64)错误解决
- 有限自动机的构造与识别
- 自定义JPA之AttributeConverter