在 Spring 源码系列: BeanFactory 的创建 文章中我们谈到了 BeanFactory 这容器, 这个里面提供了注入的实现接口. 其具体的实现还需要从 AbstractBeanFactory 和 DefaultListableBeanFactory 中来看. 今天就先撸一下 AbstractBeanFactory 这个类中的 getBean 这个方法.
1,getBean 方法
getBean 提供了四个重载方法, 如下:
// 通过 name 获取 Bean
@Override
public Object getBean(String name) throws BeansException {
return doGetBean(name, null, null, false);
}
// 通过 name 和类型获取 Bean
@Override
public <T> T getBean(String name, Class<T> requiredType) throws BeansException {
return doGetBean(name, requiredType, null, false);
}
// 通过 name 和对象参数获取 Bean
@Override
public Object getBean(String name, Object... args) throws BeansException {
return doGetBean(name, null, args, false);
}
// 通过 name, 类型和参数获取 Bean
public <T> T getBean(String name, Class<T> requiredType, Object... args) throws BeansException {
return doGetBean(name, requiredType, args, false);
}
从这四个重载方法的方法体中可以看出, 他们都是通过 doGetBean 来实现的. 所以 doGetBean 其实才是真正获取 Bean 的地方, 也是触发依赖注入发生的地方.(这个方法比较长, 分段来说)
2,doGetBean
先来看下方法的定义:
@SuppressWarnings("unchecked")
protected <T> T doGetBean(
final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
throws BeansException {
name 要检索的 bean 的名称
requiredType 要检索的 bean 所需的类型
args 使用显式参数创建 bean 实例时使用的参数 (仅在创建新实例时应用, 而不是在检索现有实例时应用)
typeCheckOnly 是否为类型检查而获得实例, 而不是实际使用
// 返回 bean 名称, 剥离工厂引用前缀, 并将别名解析为规范名称.
final String beanName = transformedBeanName(name);
// 声明当前需要返回的 bean 对象
Object bean;
// 先从缓存中获取 bean, 处理已经被创建的单例模式的 bean,
// 对于此类 bean 的请求不需要重复的创建 (singleton)
Object sharedInstance = getSingleton(beanName);
如果当前获取到的 sharedInstance 不为 null 并且参数为空, 则进行 FactoryBean 的相关处理, 并获取 FactoryBean 的处理结果.
if (sharedInstance != null && args == null) {
if (logger.isDebugEnabled()) {
// 返回指定的 singleton bean 是否正在创建 (在整个工厂内).
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 + "'");
}
}
// 完成 FactoryBean 的相关处理, 并用来获取 FactoryBean 的处理结果
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
如果当前获取到的 sharedInstance 为 null, 我们再来看下做了哪些处理 (下面的都在一个大的 else 里面):
else {
// 分解到下面
}
// 在当前线程中, 返回指定的 prototype bean 是否正在创建.
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
下面这段的作用是对 Ioc 容器中的 BeanDefinition 是否存在进行检测, 先是检测当前 BeanFactory 中是否能够获取到, 如果取不到则继续到双亲容器中进行尝试获取, 如果双亲还是取不到, 则继续向上一级父容器中尝试获取.
// 检查该工厂是否存在 bean 定义.
BeanFactory parentBeanFactory = getParentBeanFactory();
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
// 如果没有, 则继续检查父类
String nameToLookup = originalBeanName(name);
if (args != null) {
// 用明确的参数代表父项.
return (T) parentBeanFactory.getBean(nameToLookup, args);
} else {
// 如果没有 args - > 委托给标准的 getBean 方法.
return parentBeanFactory.getBean(nameToLookup, requiredType);
}
}
将指定的 bean 标记为已经创建 (或即将创建); 这里允许 bean 工厂优化其缓存以重复创建指定的 bean.
if (!typeCheckOnly) {
markBeanAsCreated(beanName);
}
先根据 beanName 来获取 BeanDefinition, 然后获取当前 bean 的所有依赖 bean, 这里是通过递归调用 getBean 来完成, 直到没有任何依赖的 bean 为止.
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
// 检查给定的合并 bean 定义, 可能抛出验证异常.
checkMergedBeanDefinition(mbd, beanName, args);
// 保证当前 bean 依赖的 bean 的初始化.
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
for (String dep: dependsOn) {
if (isDependent(beanName, dep)) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Circular depends-on relationship between'" + beanName + "'and'" + dep + "'");
}
registerDependentBean(dep, beanName);
// 递归处理依赖 bean
getBean(dep);
}
}
下面这段就是创建一个 bean 实例; 这里通过调用 getSingleton 方法来创建一个单例 bean 实例; 从代码中可以看到, getSingleton 的调用是通过 getObject 这个回调函数来间接调用 createBean 完成的.
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, new ObjectFactory < Object > () {
// 回调函数 getObject
@Override public Object getObject() throws BeansException {
try {
// 创建 bean
return createBean(beanName, mbd, args);
} catch(BeansException ex) {
// 发生异常则销毁
destroySingleton(beanName);
throw ex;
}
}
});
// 获取给定 bean 实例的对象, 无论是 bean 实例本身, 还是 FactoryBean 创建的对象.
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
下面是创建 prototype bean
else if (mbd.isPrototype()) {
Object prototypeInstance = null;
try {
beforePrototypeCreation(beanName);
// 创建 prototype bean
prototypeInstance = createBean(beanName, mbd, args);
} finally {
afterPrototypeCreation(beanName);
}
bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
}
最后是对创建的 bean 进行类型检查, 没有问题就返回已经创建好的 bean; 此时这个 bean 是包含依赖关系的 bean
if (requiredType != null && bean != null && !requiredType.isAssignableFrom(bean.getClass())) {
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;
getBean 是依赖注入的起点, 从上面的分析可以看出, bean 的创建都是通过 createBean 来完成具体的创建的. createBean 的具体实现是在 AbstractAutowireCapableBeanFactory 中的, 这里 createBean 不仅仅负责创建 bean, 还需要完成对 bean 的初始化.
来源: https://juejin.im/post/5a7532746fb9a0633a70d57f