我们先看AbstractBeanFactory.getBean方法,这个方法通过bean名称类型等信息获取类实例,如果实例不存在则生产并缓存。

    //---------------------------------------------------------------------
// Implementation of BeanFactory interface
//--------------------------------------------------------------------- @Override
public Object getBean(String name) throws BeansException {
return doGetBean(name, null, null, false);
}

关键方法doGetBean解读如下

    /**
* Return an instance, which may be shared or independent, of the specified bean.
* 返回一个共享或独立实例(单例或者多实例)
* @param name the name of the bean to retrieve
* bean名称
* @param requiredType the required type of the bean to retrieve
* 期望返回的bean类型
* @param args arguments to use when creating a bean instance using explicit arguments
* (only applied when creating a new instance as opposed to retrieving an existing one)
* 实例初始化参数(构造函数参数)
* @param typeCheckOnly whether the instance is obtained for a type check,
* not for actual use
* 标志是否仅仅检查类型
* @return an instance of the bean
* 返回bean实例
* @throws BeansException if the bean could not be created
*/
@SuppressWarnings("unchecked")
protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException { // bean名称转换,包括别名转换和&前缀处理(&前缀用于工厂类)
final String beanName = transformedBeanName(name);
Object bean; // Eagerly check singleton cache for manually registered singletons.
// 单例模式下优先使用已经创建的实例,已经在创建中则等待
Object sharedInstance = getSingleton(beanName);
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 + "'");
}
}
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
} else {
// Fail if we're already creating this bean instance:
// We're assumably within a circular reference.
// 防止类环形依赖创建时出现死锁
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
} // Check if bean definition exists in this factory.
// 检查父工厂是否存在这个类实例
BeanFactory parentBeanFactory = getParentBeanFactory();
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
// Not found -> check parent.
String nameToLookup = originalBeanName(name);
if (parentBeanFactory instanceof AbstractBeanFactory) {
return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
nameToLookup, requiredType, args, typeCheckOnly);
}
else if (args != null) {
// Delegation to parent with explicit args.
return (T) parentBeanFactory.getBean(nameToLookup, args);
}
else {
// No args -> delegate to standard getBean method.
return parentBeanFactory.getBean(nameToLookup, requiredType);
}
} // 实例创建前上锁
if (!typeCheckOnly) {
markBeanAsCreated(beanName);
} try {
// 获取bean配置,这里会把配置转化为RootBeanDefinition
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
// 检查配置是否为抽象类
checkMergedBeanDefinition(mbd, beanName, args); // Guarantee initialization of beans that the current bean depends on.
// 优先加载依赖类
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);
getBean(dep);
}
} // Create bean instance.
// 创建单例
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, () -> {
try {
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
// Explicitly remove instance from singleton cache: It might have been put there
// eagerly by the creation process, to allow for circular reference resolution.
// Also remove any beans that received a temporary reference to the bean.
destroySingleton(beanName);
throw ex;
}
});
// 1、 如果有其他类依赖此类,需要进行通知
// 2、 如果此类是工厂类,一般需要调用工厂方法返回类实例,而不是直接返回工厂类
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
// 创建多实例
else if (mbd.isPrototype()) {
// It's a prototype -> create a new instance.
Object prototypeInstance = null;
try {
beforePrototypeCreation(beanName);
prototypeInstance = createBean(beanName, mbd, args);
}
finally {
afterPrototypeCreation(beanName);
}
bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
} 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, () -> {
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;
}
} // Check if required type matches the type of the actual bean instance.
// 如果传入了类型,则会进行类型转换
if (requiredType != null && !requiredType.isInstance(bean)) {
try {
T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);
if (convertedBean == null) {
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
}
return convertedBean;
}
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());
}
}
return (T) bean;
}

关键代码getSingleton下一讲继续研究。

Spring源码阅读(二)的更多相关文章

  1. Spring 源码阅读 二

    程序入口: 接着上一篇博客中看完了在AnnotationConfigApplicationContext的构造函数中的register(annotatedClasses);将我们传递进来的主配置类添加 ...

  2. Bean实例化(Spring源码阅读)-我们到底能走多远系列(33)

    我们到底能走多远系列(33) 扯淡: 各位:    命运就算颠沛流离   命运就算曲折离奇   命运就算恐吓着你做人没趣味   别流泪 心酸 更不应舍弃   ... 主题: Spring源码阅读还在继 ...

  3. 搭建 Spring 源码阅读环境

    前言 有一个Spring源码阅读环境是学习Spring的基础.笔者借鉴了网上很多搭建环境的方法,也尝试了很多,接下来总结两种个人认为比较简便实用的方法.读者可根据自己的需要自行选择. 方法一:搭建基础 ...

  4. 初始化IoC容器(Spring源码阅读)

    初始化IoC容器(Spring源码阅读) 我们到底能走多远系列(31) 扯淡: 有个问题一直想问:各位你们的工资剩下来会怎么处理?已婚的,我知道工资永远都是不够的.未婚的你们,你们是怎么分配工资的? ...

  5. Spring源码阅读-ApplicationContext体系结构分析

    目录 继承层次图概览 ConfigurableApplicationContext分析 AbstractApplicationContext GenericApplicationContext Gen ...

  6. Sping学习笔记(一)----Spring源码阅读环境的搭建

    idea搭建spring源码阅读环境 安装gradle Github下载Spring源码 新建学习spring源码的项目 idea搭建spring源码阅读环境 安装gradle 在官网中下载gradl ...

  7. Spring源码阅读总结(Ing)

    一.Spring源码架构 Spring源码地址 二.Spring中的设计模式 1.工厂模式 BeanFactory 2.模板模式 模板的使用者只需设计一个具体的类,集成模板类,然后定制那些具体方法,这 ...

  8. Spring源码阅读笔记02:IOC基本概念

    上篇文章中我们介绍了准备Spring源码阅读环境的两种姿势,接下来,我们就要开始探寻这个著名框架背后的原理.Spring提供的最基本最底层的功能是bean容器,这其实是对IoC思想的应用,在学习Spr ...

  9. Spring源码阅读 之 配置的读取,解析

    在上文中我们已经知道了Spring如何从我们给定的位置加载到配置文件,并将文件包装成一个Resource对象.这篇文章我们将要探讨的就是,如何从这个Resouce对象中加载到我们的容器?加载到容器后又 ...

  10. spring源码分析(二)Aop

    创建日期:2016.08.19 修改日期:2016.08.20-2016.08.21 交流QQ:992591601 参考资料:<spring源码深度解析>.<spring技术内幕&g ...

随机推荐

  1. opencv车流量统计算法

    #include "cv.h" #include <cxcore.h> #include <highgui.h> #include <cvaux.h& ...

  2. vue-router重新定向、redirect与alias区别

    redirect app.vue <router-link to="/goParams/918/i like vue">goParams</router-link ...

  3. elasticsearch中文分词器ik-analyzer安装

    前面我们介绍了Centos安装elasticsearch 6.4.2 教程,elasticsearch内置的分词器对中文不友好,只会一个字一个字的分,无法形成词语,别急,已经有大拿把中文分词器做好了, ...

  4. TCP/IP协议栈基础知识

    设计思想 把一个复杂的事物进行分层划分,使得每个部分变得相对简单 分层模型 OSI分为7层模型   tcp/ip分为四层模型 应用层(Application) 传输层(Transport) 网络层(I ...

  5. 初学git

    初学git,总结了一点东西,可能有理解和操作的不到位的地方,还有就是这个是我之前写在word上的,因为CSDN上不能直接上传,所以拷贝的过程中也可能有其他问题.发的的朋友还望指正... 1.找到“参与 ...

  6. vue/cli 3.0 font-size随屏幕大小变化而变化 rem设置

    在安装cube-ui框架时 安装成功后在[E:\WWW\xxx\node_modules\vue-cli-plugin-cube-ui\generator\rem\index.js]修改remUnit ...

  7. RabbitMQ -- unacked

    RabbitMQ解决大量unacked问题 为了快速响应用户请求,我们需要消息异步处理机制,比较简单的做法是用redis的List结构,我们项目使用更专业的RabbitMQ.关于redis和Rabbi ...

  8. [Java in NetBeans] Lesson 01. Java Programming Basics

    这个课程的参考视频在youtube. 主要学到的知识点有: Create new project, choose Java Application. one .jar file/ package(.j ...

  9. Linux学习笔记:常用100条命令(三)

    linux常用命令 1.查看当前yum源 yum list 2.查看电脑以及操作系统的相关信息 uname -a 3.查看当前版本信息 cat /proc/version 4.查看发行版本信息 cat ...

  10. CentOS6.5下实现R绘图

    1.首先安装R的绘图包Cairo 下载地址:http://www.rforge.net/Cairo/files/ [root@Hadoop-NN-01 mysofts]# R CMD INSTALL ...