[TOC]
<br/>
<br/>
> ## `BeanFactory` `getBean(name)`
![](https://i.loli.net/2019/03/14/5c89f22fd5838.png)
> ### `BeanFactory`
![](https://i.loli.net/2019/03/13/5c888d04acd85.png)
* `BeanFactory`
```
public interface BeanFactory {
//这里是对FactoryBean的转义定义,因为如果使用bean的名字检索FactoryBean得到的对象是工厂生成的对象
String FACTORY_BEAN_PREFIX = "&";
//这里根据bean的名字,在IOC容器中得到bean实例,这个IOC容器就是一个大的抽象工厂。
Object getBean(String name) throws BeansException;
//这里根据bean的名字和Class类型来得到bean实例,和上面的方法不同在于它会抛出异常:如果根据名字取得的bean实例的Class类型和需要的不同的话。
<T> T getBean(String name, Class<T> requiredType);
<T> T getBean(Class<T> requiredType) throws BeansException;
Object getBean(String name, Object... args) throws BeansException;
//这里提供对bean的检索,看看是否在IOC容器有这个名字的bean
boolean containsBean(String name);
//这里根据bean名字得到bean实例,并同时判断这个bean是不是单件
boolean isSingleton(String name) throws NoSuchBeanDefinitionException;
//这里根据bean名字得到bean实例,并同时判断这个bean是不是原型
boolean isPrototype(String name) throws NoSuchBeanDefinitionException;
//这里对得到bean实例的Class类型
Class<?> getType(String name) throws NoSuchBeanDefinitionException;
//这里得到bean的别名,如果根据别名检索,那么其原名也会被检索出来
String[] getAliases(String name);
}
```
* `HierarchicalBeanFactory`,是为了实现bean工厂的层级关系提供支持,其中声明两个方法
```
//得到父工厂
BeanFactory getParentBeanFactory();
//在本地工厂中有没有给定名称的bean,不包括继承的工厂
boolean containsLocalBean(String name);
```
<br/>
> ### `getBean()`
```
public Object getBean(String name) throws BeansException {
return doGetBean(name, null, null, false);
}
protected <T> T doGetBean(
final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
throws BeansException {
// beanName转换 1、移除&开头的字符 2、处理alis别名
final String beanName = transformedBeanName(name);
Object bean;
//从bean的实例缓存中获取,singletonObjects缓存,map结构 Map<beanName, beanInstance>
Object sharedInstance = getSingleton(beanName);
// sharedInstance = null,缓存里还没有对应的实例,表明这个实例还没创建。
// BeanFactory 并不会在一开始就将所有的单例 bean 实例化好,而是在调用 getBean 获取时再实例化,懒加载
// ApplicatioContext会在spring启动时先将所有的bean都加载好
// getBean 方法有很多重载,比如 getBean(String name, Object... args)
// BeanFactory 会根据这些参数 args 去匹配合适的构造方法构造 bean 实例。
if (sharedInstance != null && args == null) {
if (logger.isDebugEnabled()) {
if (isSingletonCurrentlyInCreation(beanName)) {
logger.debug("Returning eagerly cached instance of singleton bean '" + beanName +
"' that is not fully initialized yet - a consequence of a circular reference");
}
else {
logger.debug("Returning cached instance of singleton bean '" + beanName + "'");
}
}
//如果 sharedInstance 是普通的单例 bean,下面的方法会直接返回
//如果sharedInstance 是 FactoryBean 类型的,则需调用 getObject 工厂方法获取真正的bean 实例
//如果用户想获取 FactoryBean 本身,这里也不会做特别的处理,直接返回
//FactoryBean 的实现类本身也是一种 bean。
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
/*
* 如果上面的条件不满足,则表明 sharedInstance 可能为空,此时 beanName 对应的 bean
* 实例可能还未创建。这里还存在另一种可能,如果当前容器有父容器,beanName 对应的 bean 实例
* 可能是在父容器中被创建了,所以在创建实例前,需要先去父容器里检查一下。
*/
else {
//如果上面的条件不满足,则表明 sharedInstance 可能为空,此时 beanName 对应的 bean还未创建
//还存在另一种可能,如果当前容器有父容器,beanName 对应的 bean 实例
可能在父容器中创建了
//所以需要检查一下父容器
// BeanFactory 不缓存 Prototype 类型的 bean,无法处理该类型 bean 的循环依赖问题
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
// 如果 sharedInstance = null,则到父容器中查找 bean 实例
BeanFactory parentBeanFactory = getParentBeanFactory();
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
// 获取 name 对应的 beanName,如果 name 是以 & 字符开头,则返回 & + beanName
String nameToLookup = originalBeanName(name);
// 根据 args 是否为空,以决定调用父容器哪个方法获取 bean
if (args != null) {
return (T) parentBeanFactory.getBean(nameToLookup, args);
}
else {
return parentBeanFactory.getBean(nameToLookup, requiredType);
}
}
if (!typeCheckOnly) {
markBeanAsCreated(beanName);
}
try {
// 合并父 BeanDefinition 与子 BeanDefinition
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);
// 检查是否有 dependsOn 依赖,如果有则先初始化所依赖的 bean
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
for (String dep : dependsOn) {
//检测是否存在 depends-on 循环依赖
//depends-on 循环,Spring 会直接
抛出异常
if (isDependent(beanName, dep)) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
}
// 注册依赖记录
registerDependentBean(dep, beanName);
try {
// 加载 depends-on 依赖
getBean(dep);
}
catch (NoSuchBeanDefinitionException ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"'" + beanName + "' depends on missing bean '" + dep + "'", ex);
}
}
}
// 创建 bean 实例
if (mbd.isSingleton()) {
/*
* 这里并没有直接调用 createBean 方法创建 bean 实例,而是通过
* getSingleton(String, ObjectFactory) 方法获取 bean 实例。
* getSingleton(String, ObjectFactory) 方法会在内部调用
* ObjectFactory 的 getObject() 方法创建 bean,并会在创建完成后,
* 将 bean 放入缓存中。关于 getSingleton 方法的分析,本文先不展开,我会在
* 后面的文章中进行分析
*/
sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
@Override
public Object getObject() throws BeansException {
try {
// 创建 bean 实例
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
destroySingleton(beanName);
throw ex;
}
}
});
// 如果 bean 是 FactoryBean 类型,则调用工厂方法获取真正的 bean 实例。否则直接返回 bean 实例
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
// 创建 prototype 类型的 bean 实例
else if (mbd.isPrototype()) {
Object prototypeInstance = null;
try {
beforePrototypeCreation(beanName);
prototypeInstance = createBean(beanName, mbd, args);
}
finally {
afterPrototypeCreation(beanName);
}
bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
}
// 创建其他类型的 bean 实例
else {
String scopeName = mbd.getScope();
final Scope scope = this.scopes.get(scopeName);
if (scope == null) {
throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
}
try {
Object scopedInstance = scope.get(beanName, new ObjectFactory<Object>() {
@Override
public Object getObject() throws BeansException {
beforePrototypeCreation(beanName);
try {
return createBean(beanName, mbd, args);
}
finally {
afterPrototypeCreation(beanName);
}
}
});
bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
}
catch (IllegalStateException ex) {
throw new BeanCreationException(beanName,
"Scope '" + scopeName + "' is not active for the current thread; consider " +
"defining a scoped proxy for this bean if you intend to refer to it from a singleton",
ex);
}
}
}
catch (BeansException ex) {
cleanupAfterBeanCreationFailure(beanName);
throw ex;
}
}
// 如果需要进行类型转换,则在此处进行转换。类型转换这一块我没细看,就不多说了。
if (requiredType != null && bean != null && !requiredType.isInstance(bean)) {
try {
return getTypeConverter().convertIfNecessary(bean, requiredType);
}
catch (TypeMismatchException ex) {
if (logger.isDebugEnabled()) {
logger.debug("Failed to convert bean '" + name + "' to required type '" +
ClassUtils.getQualifiedName(requiredType) + "'", ex);
}
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
}
}
// 返回 bean
return (T) bean;
}
```
> ### `beanName`转换
* 处理以字符 `&` 开头的 `name`,处理别名。
```
protected String transformedBeanName(String name) {
// 这里调用了两个方法:
// BeanFactoryUtils.transformedBeanName(name) 处理&字符
//canonicalName 转换别名
return canonicalName(BeanFactoryUtils.transformedBeanName(name));
}
```
<br/>
> ### 从缓存中获取`bean`实例。
* 对于单例`bean`,`Spring`容器只会实例化一次。后续再次获取时,只需直接从缓存里获取即可,无需且不能再次实例化。
* 从缓存中取`bean`实例的方法是`getSingleton(String)`。
```
public Object getSingleton(String beanName) {
return getSingleton(beanName, true);
}
// allowEarlyReference表示是否允许其他 bean 引用正在创建中的 bean,用于处理循环引用的问题。
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
// 从 singletonObjects 获取实例,singletonObjects 中缓存的实例都是完全实例化好的 bean,可以直接使用
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
synchronized (this.singletonObjects) {
// 从 earlySingletonObjects 中获取提前曝光的 bean,用于处理循环引用
singletonObject = this.earlySingletonObjects.get(beanName);
// 如果如果 singletonObject = null,且允许提前曝光 bean 实例,则从相应的 ObjectFactory 获取一个原始的(raw)bean(尚未填充属性)
if (singletonObject == null && allowEarlyReference) {
// 获取相应的工厂类,获取对应beanName的工厂类
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
// 提前曝光 bean 实例,用于解决循环依赖
//此处为实际创建bean实例
singletonObject = singletonFactory.getObject();
// 放入上级缓存,如果还有其他 bean 依赖当前 bean,其他 bean 可以直接从 earlySingletonObjects 取结果
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
}
}
}
}
return (singletonObject != NULL_OBJECT ? singletonObject : null);
}
```
* 其中涉及了三个缓存
![](https://i.loli.net/2019/03/12/5c87952a56166.png)
<br/>
> ### 合并父 BeanDefinition 与 子 BeanDefinition
* `Spring` 支持配置继承,在标签中可以使用`parent`属性配置父类 `bean`。这样子类 `bean` 可以继承父类 `bean` 的配置信息,同时也可覆盖父类中的配置。比如下面的配置:
```
<bean id="hello" class="xyz.coolblog.innerbean.Hello">
<property name="content" value="hello"/>
</bean>
<bean id="hello-child" parent="hello">
<property name="content" value="I`m hello-child"/>
</bean>
```
<br/>
> ### 从 `FactoryBean` 中获取 `bean` 实例
* 单例类型,将`FactoryBean`生成的`bean`放入缓存
* 非单例,每次创建新的`bean`
***
> ### 参考
#### [Spring IOC 容器源码分析 - 循环依赖的解决办法](https://segmentfault.com/a/1190000015221968)
#### [Spring IOC 容器源码分析 - 获取单例 bean](http://www.tianxiaobo.com/2018/06/01/Spring-IOC-%E5%AE%B9%E5%99%A8%E6%BA%90%E7%A0%81%E5%88%86%E6%9E%90-%E8%8E%B7%E5%8F%96%E5%8D%95%E4%BE%8B-bean/)
#### [Spring IOC 容器源码分析系列文章](http://www.tianxiaobo.com/2018/05/30/Spring-IOC-%E5%AE%B9%E5%99%A8%E6%BA%90%E7%A0%81%E5%88%86%E6%9E%90%E7%B3%BB%E5%88%97%E6%96%87%E7%AB%A0%E5%AF%BC%E8%AF%BB/)
- asD
- Java
- Java基础
- Java编译器
- 反射
- collection
- IO
- JDK
- HashMap
- ConcurrentHashMap
- LinkedHashMap
- TreeMap
- 阻塞队列
- java语法
- String.format()
- JVM
- JVM内存、对象、类
- JVM GC
- JVM监控
- 多线程
- 基础概念
- volatile
- synchronized
- wait_notify
- join
- lock
- ThreadLocal
- AQS
- 线程池
- Spring
- IOC
- 特性介绍
- getBean()
- creatBean()
- createBeanInstance()
- populateBean()
- AOP
- 基本概念
- Spring处理请求的过程
- 注解
- 微服务
- 服务注册与发现
- etcd
- zk
- 大数据
- Java_spark
- 基础知识
- Thrift
- hdfs
- 计算机网络
- OSI七层模型
- HTTP
- SSL
- 数据库
- Redis
- mysql
- mybatis
- sql
- 容器
- docker
- k8s
- nginx
- tomcat
- 数据结构/算法
- 排序算法
- 快排
- 插入排序
- 归并排序
- 堆排序
- 计算时间复杂度
- leetcode
- LRU缓存
- B/B+ 树
- 跳跃表
- 设计模式
- 单例模式
- 装饰者模式
- 工厂模式
- 运维
- git
- 前端
- thymeleaf
- 其他
- 代码规范
- work_project
- Interview