Spring的BeanFactory是什么?
什么是BeanFactory?
提到Spring,总是让人第一时间想起IOC容器,而IOC容器的顶层核心接口就是我们的BeanFactory,如果能够理解BeanFactory的体系结构想必能让我们对Spring整体脉络有更加清晰的认知,所以,本文的探究方向主要为以下几点:
BeanFactory的体系结构是怎样的?Bean的元信息从何而来?BeanFactory生产Bean的过程是怎样的?
BeanFactory的体系结构
我们先来看看有哪些子类实现了它吧

其中ApplicationContext这一块已在上篇文章有详细说明,而DefaultListableBeanFactory这个底层实现类便理所当然的成为了我们此次探究的出发点,为了让我们有个更好的观感,以下是纯粹的BeanFactoryUML图:

我们可以看到DefaultListableBeanFactory实现的接口有:
SingletonBeanRegistry: 定义了对单例缓存池相关的操作,如将bean注册到单例缓存池中ConfigurableBeanFactory: 可配置的BeanFactory,定义了各种各样的配置能力,如bean的作用域,bean的classLoader,添加bean的后置处理器,设置bean的创建状态,销毁bean等等AutowireCapableBeanFactory: 能进行自动装配的BeanFactory,这可能是我们最为熟悉的BeanFactory,定义了自动装配的类型(byName/byType),createBean,autowireBean, 自动装配属性, populateBean, initializeBean, 对于与bean生命周期相关的方法都将在这里体现ListableBeanFactory: 对BeanFactory的增强,定义了一系列根据beanType获取bean或者beanName的方法ConfigurableListableBeanFactory: 对ConfigurableBeanFactory的增强,定义了忽略bean的类型、缓存bean定义、预实例化单例bean等方法BeanDefinitionRegistry: bean定义注册器,定义了与bean定义相关的方法
如果说以上的接口体现了DefaultListableBeanFactory具备的功能,那么它所继承的一系列类就是这些功能的实现:
DefaultSingletonBeanRegistry: 单例bean注册器,定义了三级缓存,其实就是三个Map属性FactoryBeanRegistrySupport: 提供对FactoryBean的支持AbstractBeanFactory: 实现了一系列操作IOC容器的功能,但最终的createBean依旧交由子类AbstractAutowireCapableBeanFactory完成AbstractAutowireCapableBeanFactory: 实现了创建bean的功能,所有与创建bean的相关的功能都在这里DefaultListableBeanFactory: 在以上父类的功能基础上实现了ConfigurableBeanFactory和BeanDefinitionRegistry接口,定义了一些存放Bean定义相关信息的Map
看到这里,想必对
DefaultListableBeanFactory已经有一个大致的了解了,那么问题来啦,我们应该怎么从容器中获取一个bean呢?是不是只要通过BeanDefinitionRegistry注册一个bean定义,再通过AutowireCapableBeanFactory去createBean就完成了呢?就像下面这样:
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
RootBeanDefinition beanDefinition = new RootBeanDefinition(Wheel.class);
beanFactory.registerBeanDefinition("wheel",beanDefinition);
beanFactory.getBean("wheel", Wheel.class);
Bean的元信息从何而来?
我们现在已经知道DefaultListableBeanFactory的大致功能了,我们发现当我们想要创建一个Bean的时候,总是离不开一个名词:Bean定义,那么这个Bean定义究竟是什么呢?
BeanDefinition其实是一个接口,并不是一个具体的类,我们也可以看一下它的UML图:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

可以发现这里使用了模板方法的设计模式扩展了许多的子类,其中我们最常用的为RootBeanDefinition,它主要包含的属性如下:

我们向容器中注册的Bean定义的信息大概就是如此,当BeanFactory生产Bean时,便可以通过beanClass清楚的知道Bean的类是什么,作用域是怎样,是否懒加载,init方法是什么等等等等
咦,如果一个最简单的bean,好像可以直接通过反射就搞定了耶~
具体结构已经清楚了,那我们来看一下注册过程吧
先从Demo看起
public static void main(String[] args) {
//创建一个DefaultListableBeanFactory实例
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
//创建一个BeanDefinition
RootBeanDefinition beanDefinition = new RootBeanDefinition(Wheel.class);
//将BeanDefinition注册到容器中
beanFactory.registerBeanDefinition("wheel",beanDefinition);
}
public static class Wheel {
}
创建BeanDefinition
public RootBeanDefinition(@Nullable Class<?> beanClass) {
//初始化父类
super();
//将beanClass赋值给this.BeanClass
setBeanClass(beanClass);
}
初始化父类
//将其中一部分属性赋予默认值
autowireCandidate = true;
primary = false;
protected AbstractBeanDefinition() {
this(null, null);
}
protected AbstractBeanDefinition(@Nullable ConstructorArgumentValues cargs, @Nullable MutablePropertyValues pvs) {
this.constructorArgumentValues = cargs;
this.propertyValues = pvs;
}
将BeanDefinition注册到容器中
//除去校验逻辑,注册时只做了这两步操作
this.beanDefinitionMap.put(beanName, beanDefinition);
this.beanDefinitionNames.add(beanName);
看到这里,大家伙可能会充满疑问?what? 就这样?没有填充属性的步骤吗?嘿嘿,BeanFactory是一个纯粹的工厂,只负责生产Bean,是没有装配(设计)BeanDefinition的功能的,专业的事还是交给专业的人做,设计的事情还是交由ApplicationContext完成的。
那在ApplicationContext中是怎么完成一个BeanDefinition的呢?还记得预启动将配置类注册到容器中时有这样一段代码吗?以下代码为AnnotatedBeanDefinitionReader#doRegisterBean中的摘要部分:
<T> void doRegisterBean(Class<T> annotatedClass, @Nullable Supplier<T> instanceSupplier, @Nullable String name,
@Nullable Class<? extends Annotation>[] qualifiers, BeanDefinitionCustomizer... definitionCustomizers) {
//.......代码
//处理普通的bean定义注解,@Lazy @Primary @DependsOn @Role @Description
AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);
//......代码
}
而非配置的Bean是通过在预启动时注册的配置类后置处理器ConfigurationClassPostProcessor#processConfigBeanDefinitions中完成的,以下代码为ClassPathBeanDefinitionScanner#doScan中的摘要部分,详细调用链将在后面的文章进行说明
//传入我们配置类的包路径
protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<>();
for (String basePackage : basePackages) {
//寻找到所有标识了@Component注解的BeanDefinition
Set<BeanDefinition> candidates = findCandidateComponents(basePackage);
for (BeanDefinition candidate : candidates) {
//....省略代码
if (candidate instanceof AbstractBeanDefinition) {
//处理BeanDefinition
postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);
}
if (candidate instanceof AnnotatedBeanDefinition) {
//处理普通的bean定义注解,@Lazy @Primary @DependsOn @Role @Description
AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
}
//...省略代码
//将BeanDefinition注册到容器中
registerBeanDefinition(definitionHolder, this.registry);
}
}
处理BeanDefinition
protected void postProcessBeanDefinition(AbstractBeanDefinition beanDefinition, String beanName) {
//设置默认值
beanDefinition.applyDefaults(this.beanDefinitionDefaults);
//这里默认为空
if (this.autowireCandidatePatterns != null) {
beanDefinition.setAutowireCandidate(PatternMatchUtils.simpleMatch(this.autowireCandidatePatterns, beanName));
}
}
设置默认值
public void applyDefaults(BeanDefinitionDefaults defaults) {
//默认为null
Boolean lazyInit = defaults.getLazyInit();
if (lazyInit != null) {
setLazyInit(lazyInit);
}
//默认为0
setAutowireMode(defaults.getAutowireMode());
//默认为0
setDependencyCheck(defaults.getDependencyCheck());
//默认为null
setInitMethodName(defaults.getInitMethodName());
setEnforceInitMethod(false);
//默认为null
setDestroyMethodName(defaults.getDestroyMethodName());
setEnforceDestroyMethod(false);
}
处理普通的bean定义注解
public static void processCommonDefinitionAnnotations(AnnotatedBeanDefinition abd) {
processCommonDefinitionAnnotations(abd, abd.getMetadata());
}
static void processCommonDefinitionAnnotations(AnnotatedBeanDefinition abd, AnnotatedTypeMetadata metadata) {
//从元数据中取出该注解的属性列表,不为空说明有标识该注解
AnnotationAttributes lazy = attributesFor(metadata, Lazy.class);
if (lazy != null) {
abd.setLazyInit(lazy.getBoolean("value"));
}
else if (abd.getMetadata() != metadata) {
lazy = attributesFor(abd.getMetadata(), Lazy.class);
if (lazy != null) {
abd.setLazyInit(lazy.getBoolean("value"));
}
}
//判断元数据中是否有该注解
if (metadata.isAnnotated(Primary.class.getName())) {
abd.setPrimary(true);
}
AnnotationAttributes dependsOn = attributesFor(metadata, DependsOn.class);
if (dependsOn != null) {
abd.setDependsOn(dependsOn.getStringArray("value"));
}
AnnotationAttributes role = attributesFor(metadata, Role.class);
if (role != null) {
abd.setRole(role.getNumber("value").intValue());
}
AnnotationAttributes description = attributesFor(metadata, Description.class);
if (description != null) {
abd.setDescription(description.getString("value"));
}
}
attributesFor(metadata, Lazy.class)
static AnnotationAttributes attributesFor(AnnotatedTypeMetadata metadata, Class<?> annotationClass) {
return attributesFor(metadata, annotationClass.getName());
}
static AnnotationAttributes attributesFor(AnnotatedTypeMetadata metadata, String annotationClassName) {
//metadata为beanClass的注解元数据,存放了该类所配置的所有注解
//annotationClassName为需要寻找的注解名称
return AnnotationAttributes.fromMap(metadata.getAnnotationAttributes(annotationClassName, false));
}
default Map<String, Object> getAnnotationAttributes(String annotationName,
boolean classValuesAsString) {
//遍历元数据中的所有注解
MergedAnnotation<Annotation> annotation = getAnnotations().get(annotationName,
null, MergedAnnotationSelectors.firstDirectlyDeclared());
//不存在则返回null,否则返回一个map
if (!annotation.isPresent()) {
return null;
}
return annotation.asAnnotationAttributes(Adapt.values(classValuesAsString, true));
}
以上为扫描@Component注解类进行解析元数据填充属性的逻辑,在配置类中以@Bean方式注册的BeanDefinition填充属性过程在ConfigurationClassBeanDefinitionReader.loadBeanDefinitions(configClasses)
BeanFactory生产Bean的过程是怎样的?
现在,我们已经知道了一个BeanDefinition的具体结构以及是如何产生并注册到BeanFactory的,那么BeanFactory又是如何使用它生产Bean的呢?以下附上createBean的粗略流程图,具体细节将放在IOC容器启动流程中详细说明

那么关于
BeanFactory的相关内容就到这里了,希望大家有所收获,下篇将正式进入Spring IOC容器的启动流程!
准备花个30天时间,系统的来整理一下我对spring源码的认识:
Spring 源码系列
- Spring源码分析之 IOC 容器预启动流程(已完结)
- Spring源码分析之BeanFactory体系结构(已完结)
- Spring源码分析之BeanFactoryPostProcessor调用过程(已完结)
- Spring源码分析之Bean的创建过程
- Spring源码分析之什么是循环依赖及解决方案
- Spring源码分析之AOP从解析到调用
- Spring源码分析之事务管理(上),事物管理是spring作为容器的一个特点,总结一下他的基本实现与原理吧
- Spring源码分析之事务管理(下) ,关于他的底层事物隔离与事物传播原理,重点分析一下
Spring Mvc 源码系列
- SpringMvc体系结构
- SpringMvc源码分析之Handler解析过程
- SpringMvc源码分析之请求链过程
Mybatis 源码系列
暂定
追更,可扫下面的二维码,分享纯粹为了乐趣,也有一种成就感吧,笔者这篇文章先就到这

Spring的BeanFactory是什么?的更多相关文章
- Spring之BeanFactory及Bean生命周期
1.spring通过BeanFactory灵活配置.管理bean,Spring对管理的bean没有任何特别的要求,完全支持对POJO的管理: 2.BeanFactory有个ApplicationCon ...
- spring之BeanFactory
spring的IOC容器能够帮我们自动new对象,对象交给spring管之后我们不用自己手动去new对象了.那么它的原理是什么呢?是怎么实现的呢?下面我来简单的模拟一下spring的机制,相信看完之后 ...
- Spring 之BeanFactory(转)
BeanFactory是Spring的“心脏”.它就是Spring IoC容器的真面目. Spring使用BeanFactory来实例化.配置和管理Bean.但是,在大多数情况我们并不直接使用Bean ...
- 简单实现Spring中BeanFactory原理
上一篇文章介绍了Java反射机制在Spring IOC中的应用,知道了BeanFactory底层的实现原理. 原理搞懂了,对Spring IOC理解起来也很容易. 先来看看Java代码获取Spring ...
- Spring的BeanFactory体系结构(一)
本文使用的代码是: Spring 3.0 接 触Spring也有很长一段时间了.但是,每次都是直接使用Spring直接提供的API,时间久了,自然也会想探索Spring里面的奥秘.今天上 午,整理出了 ...
- 十、Spring之BeanFactory源码分析(二)
Spring之BeanFactory源码分析(二) 前言 在前面我们简单的分析了BeanFactory的结构,ListableBeanFactory,HierarchicalBeanFactory,A ...
- 九、Spring之BeanFactory源码分析(一)
Spring之BeanFactory源码分析(一) 注意:该随笔内容完全引自https://blog.csdn.net/u014634338/article/details/82865644,写的 ...
- Spring中BeanFactory与FactoryBean的区别
在Spring中有BeanFactory和FactoryBean这2个接口,从名字来看很相似,比较容易搞混. 一.BeanFactory BeanFactory是一个接口,它是Spring中工厂的顶层 ...
- 【Java面试】Spring中 BeanFactory和FactoryBean的区别
一个工作了六年多的粉丝,胸有成竹的去京东面试. 然后被Spring里面的一个问题卡住,唉,我和他说,6年啦,Spring都没搞明白? 那怎么去让面试官给你通过呢? 这个问题是: Spring中Bean ...
- 【Spring】BeanFactory解析bean详解
在该文中来讲讲Spring框架中BeanFactory解析bean的过程,该文之前在小编原文中有发表过,要看原文的可以直接点击原文查看,先来看一个在Spring中一个基本的bean定义与使用. pac ...
随机推荐
- iOS审核被拒大全
崩溃和bug 当你完成应用开发并准备发布时应该将App提交审核.在提交审核前,要确保已经在设备上对应用程序进行了彻底的测试,修复了所有的bug. 断掉的链接 应用程序中所有的链接必须是功能性的.对于所 ...
- Google Kick Start 2020 Round C
ac代码 A. Countdown for循环跑一跑,没啥好说的. B. Stable Wall 如果\(s_{i,j} \ne s_{i+1,j}\),那么说明\(s_{i+1,j}\)必须在\(s ...
- C++中的输入输出
update&fixed: 经过实测,io解绑在各大oj以及本地评测软件上都劣于scanf 所以在大数据的情况下还是推荐尽量使用scanf! ! ! ! 众所周知,C++自带了各种输入方式 比 ...
- 剑指 Offer 42. 连续子数组的最大和
题目描述 输入一个整型数组,数组中的一个或连续多个整数组成一个子数组.求所有子数组的和的最大值. 要求时间复杂度为\(O(n)\). 示例1: 输入: nums = [-2,1,-3,4,-1,2,1 ...
- 新三种求数列中值SQL之效率再比拼
在 https://www.cnblogs.com/xiandedanteng/p/12677688.html 中我列举了三种求中值方案,其中日本人MICK的做法因为不适用于二百万结果集而放弃,取而 ...
- JS语法_其他
严格模式 let obj = { name: 'oceans', } function f1() { with (obj) { console.log(name) } } function f2() ...
- Unity3D与iOS的交互
1. 关于Unity3D Unity3D(以下简称U3D)是由Unity Technologies开发的一个让玩家轻松创建诸如三维视频游戏.建筑可视化.实时三维动画等类型互动内容的多平台的综合型游戏开 ...
- List和Dictionary的使用技巧总结
List和Dictionary想必是我们平常用到最多的C#容器了,他们使用起来都很简单,所以很多人就可能就没去深究,其实在使用过程中有很多的小技巧能让我们写的代码变得更高效也更安全. 1·合理的指定初 ...
- First-blog:解决mybatis 用mysql进行模糊搜索时,查不了中文问题
如图:点击小字 按搜索时,出现乱码搜索不了 解决办法:出现乱码问题,一般无非两种 1.是数据库问题 2.是服务器问题 我在MySQL命令行搜索时,中文可以实现,说明时服务器问题 通过修改 tomcat ...
- robotframework安装与运行(ride.py1.7.4.2命令报错)(win10+python3.8.1)
首先,robotframework必须在python的环境下运行 所以你的电脑里必须有python3.x的环境先. 上古时期的robotframework只支持python2,不过python2都已经 ...