相关源码注释
ApplicationContext
BeanFactory
getBean
AbstractBeanFactory#getBean() 方法实现是交给 doGetBean() 方法具体实现的
@Override
public Object getBean(String name) throws BeansException {
return doGetBean(name, null, null, false);
}
@Override
public <T> T getBean(String name, Class<T> requiredType) throws BeansException {
return doGetBean(name, requiredType, null, false);
}
@Override
public Object getBean(String name, Object... args) throws BeansException {
return doGetBean(name, null, args, false);
}
/**
* Return an instance, which may be shared or independent, of the specified bean.
* <p>返回一个实例,该实例可以指定bean的共享或独立</p>
* @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)
* -- 使用显示参数创建Bean实例时要使用的参数(仅在创建新实例而不是检索现有实例时才应用)
* @return an instance of the bean -- Bean的一个实例
* @throws BeansException if the bean could not be created -- 如果无法创建Bean
*/
public <T> T getBean(String name, @Nullable Class<T> requiredType, @Nullable Object... args)
throws BeansException {
//返回一个实例,该实例可以指定bean的共享或独立
return doGetBean(name, requiredType, args, false);
}
doGetBean
/*
* Return an instance, which may be shared or independent, of the specified bean.
* <p>返回一个实例,该实例可以指定bean的共享或独立</p>
* @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)
* -- 使用显示参数创建bean实例时要使用的参数(仅在创建新实例而不是检索现有实例时适用)
* @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 - 如果无法创建该bean
*/
@SuppressWarnings("unchecked")
protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
//获取name对应的规范名称【全类名】,包括以'&'开头的name
final String beanName = transformedBeanName(name);
Object bean;
// Eagerly check singleton cache for manually registered singletons.
// 译:认真检查单例缓存中是否有手动注册的单例。
// 获取beanName的单例对象,并允许创建早期引用。
// 其最终实现:DefaultSingletonBeanRegistry#getSingleton(beanName,true);
Object sharedInstance = getSingleton(beanName);
//如果bean的单例对象找到了,且 没有创建bean实例时要使用的参数
if (sharedInstance != null && args == null) {
//打印跟踪日志
if (logger.isTraceEnabled()) {
//如果当前beanName正在创建(在整个工厂内)
if (isSingletonCurrentlyInCreation(beanName)) {
logger.trace("Returning eagerly cached instance of singleton bean '" + beanName +
"' that is not fully initialized yet - a consequence of a circular reference");
}
else {
logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
}
}
//获取给定Bean实例对象,如果是FactoryBean,则可以是bean实例本身或 创建的对象
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
else {
// Fail if we're already creating this bean instance:
// We're assumably within a circular reference.
// 译:如果我们已经创建此bean实例,则失败:我们大概在循环引用之内
// 如果当前线程内,beanName正在创建中
if (isPrototypeCurrentlyInCreation(beanName)) {
//抛出异常,表明该beanName在创建时抛出异常。
throw new BeanCurrentlyInCreationException(beanName);
}
// Check if bean definition exists in this factory.
// 译:检查该工厂中是否存在bean定义
//获取当前父工厂
BeanFactory parentBeanFactory = getParentBeanFactory();
//如果父工厂存在,且 beanNeae对的定义不存在
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
// Not found -> check parent. 找不到 -> 检查父工厂
//获取name对应的规范名称【全类名】,如果name前面有'&',则会返回'&'+规范名称【全类名】
String nameToLookup = originalBeanName(name);
//如果父工厂是AbstractBeanFactory的实例
if (parentBeanFactory instanceof AbstractBeanFactory) {
//调用父工厂的doGetBean方法,就是该方法。【递归】
return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
nameToLookup, requiredType, args, typeCheckOnly);
}
else if (args != null) {//如果有创建bean实例时要使用的参数
// Delegation to parent with explicit args. 使用显示参数委派给父工厂
// 使用父工厂获取该bean对象,通bean全类名和创建bean实例时要使用的参数
return (T) parentBeanFactory.getBean(nameToLookup, args);
}
else if (requiredType != null) {
// No args -> delegate to standard getBean method.
//没有创建bean实例时要使用的参数 -> 委托给标准的getBean方法。
//使用父工厂获取该bean对象,通bean全类名和所需的bean类型
return parentBeanFactory.getBean(nameToLookup, requiredType);
}
else {
//使用父工厂获取bean,通过bean全类名
return (T) parentBeanFactory.getBean(nameToLookup);
}
}
//如果不需要检索所需的bean类型
if (!typeCheckOnly) {
//为beanName标记为已经创建(或将要创建)
markBeanAsCreated(beanName);
}
try {
//获取beanName合并后的RootBeanDefinition对象
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
//检查mbd的合法性,不合格会引发验证异常
checkMergedBeanDefinition(mbd, beanName, args);
// Guarantee initialization of beans that the current bean depends on.
// 确保当前bean依赖的bean的初始化
//获取mbd所配置的bean的所需依赖的bean名
String[] dependsOn = mbd.getDependsOn();
//如果有依赖的bean名
if (dependsOn != null) {
//遍历依赖的bean名
for (String dep : dependsOn) {
//如果beanName已注册依赖于dependentBeanName的关系
if (isDependent(beanName, dep)) {
// 抛出创建Bean异常:循环依赖关系在beanName和dep之间
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
}
//注册dep与beanName的依赖关系
registerDependentBean(dep, beanName);
try {
//递归 优先实例化被依赖的Bean
getBean(dep);
}
//捕捉为找到BeanDefinition异常:'beanName'依赖于缺少的bean'dep'
catch (NoSuchBeanDefinitionException ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"'" + beanName + "' depends on missing bean '" + dep + "'", ex);
}
}
}
// Create bean instance.
// 创建bean实例
if (mbd.isSingleton()) {
//返回以beanName的(原始)单例对象,如果尚未注册,则使用singletonFactory创建并注册一个对象:
sharedInstance = getSingleton(beanName, () -> {
try {
//为给定的合并后BeanDefinition(和参数)创建一个bean实例
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {//捕捉Bean异常
// 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.
// 显示地从单例缓存中删除实例:它可能是由创建过程急切地放在那里,以允许循环引用解析。还要删除
// 接收到该Bean临时引用的任何Bean
//销毁给定的bean。如果找到相应的一次性Bean实例,则委托给destoryBean
destroySingleton(beanName);
//重新抛出ex
throw ex;
}
});
//从 beanInstannce 中获取公开的Bean对象,主要处理beanInstance是FactoryBean对象的情况,如果不是
// FactoryBean会直接 返回beanInstance实例
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
//如果mbd指定了ProtoType作用域
else if (mbd.isPrototype()) {
// It's a prototype -> create a new instance.
// 它是一个原型 -> 创建一个新实例
//定义 proptype实例
Object prototypeInstance = null;
try {
//创建ProtoPype对象前的准备工作,默认实现 将beanName添加到 prototypesCurrentlyInCreation 中
beforePrototypeCreation(beanName);
//为mbd(和参数)创建一个bean实例
prototypeInstance = createBean(beanName, mbd, args);
}
finally {
//创建完prototype实例后的回调,默认是将beanName从 prototypesCurrentlyInCreation 移除
afterPrototypeCreation(beanName);
}
//从 beanInstannce 中获取公开的Bean对象,主要处理beanInstance是FactoryBean对象的情况,如果不是
// FactoryBean会直接 返回beanInstance实例
bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
}
else {
//获取mbd指定的Scope
String scopeName = mbd.getScope();
//从scopes中获取scopeName对于的Scope对象
final Scope scope = this.scopes.get(scopeName);
//如果scope为null
if (scope == null) {
//抛出非法状态异常:没有名为'scopeName'的scope注册
throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
}
try {
//从scope中获取beanName对应的实例对象
Object scopedInstance = scope.get(beanName, () -> {
//创建ProtoPype对象前的准备工作,默认实现 将beanName添加到 prototypesCurrentlyInCreation 中
beforePrototypeCreation(beanName);
try {
//为mbd(和参数)创建一个bean实例
return createBean(beanName, mbd, args);
}
finally {
//创建完prototype实例后的回调,默认是将beanName从 prototypesCurrentlyInCreation 移除
afterPrototypeCreation(beanName);
}
});
//从 beanInstannce 中获取公开的Bean对象,主要处理beanInstance是FactoryBean对象的情况,如果不是
// FactoryBean会直接 返回beanInstance实例
bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
}
catch (IllegalStateException ex) {//捕捉非法状态异常
//抛出Bean创建异常:作用域 'scopeName' 对于当前线程是不活动的;如果您打算从单个实例引用它,请考虑为此
// beanDefinition一个作用域代理
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) {//捕捉获取Bean对象抛出的Bean异常
//在Bean创建失败后,对缓存的元数据执行适当的清理
cleanupAfterBeanCreationFailure(beanName);
//重新抛出ex
throw ex;
}
}
// Check if required type matches the type of the actual bean instance.
// 检查 requiredType 是否与实际Bean实例的类型匹配
// 如果requiredType不为null && bean不是requiredType的实例
if (requiredType != null && !requiredType.isInstance(bean)) {
try {
//获取此BeanFactory使用的类型转换器,将bean转换为requiredType
T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);
//如果 convertedBean 为 null
if (convertedBean == null) {
//抛出 Bean不是必要类型的异常
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
}
//返回convertedBean
return convertedBean;
}
catch (TypeMismatchException ex) {//捕捉 尝试设置Bean属性时,在类型不匹配上引发异常
//如果当前日志级别是追踪级别
if (logger.isTraceEnabled()) {
//打印追踪日志:转换bean'name'到要求的类型失败
logger.trace("Failed to convert bean '" + name + "' to required type '" +
ClassUtils.getQualifiedName(requiredType) + "'", ex);
}
//抛出 Bean不是必要类型的异常
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
}
}
//将bean返回出去
return (T) bean;
}
transformedBeanName(name)
/**
* Return the bean name, stripping out the factory dereference prefix if necessary,
* and resolving aliases to canonical names.
* <p>返回Bean名称,如果必要,去除工厂取消前缀,并将别名解析为规范名称</p>
* @param name the user-specified name - 用户指定的名称
* @return the transformed bean name - 转换后的bena名称
*/
protected String transformedBeanName(String name) {
//去除开头的'&'字符,返回剩余的字符串得到转换后的Bean名称,然后通过递归形式在
// aliasMap【别名映射到规范名称集合】中得到最终的规范名称
return canonicalName(BeanFactoryUtils.transformedBeanName(name));
}
去除name开头的’&‘字符,获取name最终的规范名称【最终别名或者是全类名】:去除开头的’&'字符,返回剩余的字符串得到转换后的Bean名称, 然后通过递归形式在 aliasMap【别名映射到规范名称集合】中得到最终的规范名称
BeanFactoryUtils.transformedBeanName(name)
去除开头的’&'字符,返回剩余的字符串作为转换后的Bean名称【可能是全类名】
- 如果name为null,抛出异常
- 如果name不是以’&'开头,就直接返回
- 从具有FactoryBean前缀的名称缓存到剥离的名称的ConcurrentHashMap【transformedBenaNameCache】 中获取bean名对应的转换后的名称并返回
- 获取不到时就构建一个:从name的开头位置去掉’&’,再重新检查是否还是以’&‘开头,是的话就再截直到没有出现’&'开头为止。所得到 的字符串就是Bean名称【可能是全类名】
/**
* Return the actual bean name, stripping out the factory dereference
* prefix (if any, also stripping repeated factory prefixes if found).
* <p>返回实际的bean名称,删除工厂取消引用前缀(如果有的话,还删除重复的
* 工厂前缀(如果找到))</p>
* <p>用于获取以'&'开头的name对应的bean名,如果bean不是'&'开头,就直接返回该name</p>
* @param name the name of the bean - bean名
* @return the transformed name - 转换后的名称
* @see BeanFactory#FACTORY_BEAN_PREFIX
*/
public static String transformedBeanName(String name) {
//如果bean名为null,抛出异常
Assert.notNull(name, "'name' must not be null");
//如果bean名不是以'&'开头,就直接返回
if (!name.startsWith(BeanFactory.FACTORY_BEAN_PREFIX)) {
return name;
}
//从transformedBenaNameCache中获取bean名对应的转换后的名称
return transformedBeanNameCache.computeIfAbsent(name, beanName -> {
//从beanName的开头位置去掉'&',并重新赋值给beanName,再重新检查是还是以'&'开头,是的话就再截
// 知道开头不是以'&'开头后,加入到transformedBeanNameCache中
do {
beanName = beanName.substring(BeanFactory.FACTORY_BEAN_PREFIX.length());
}
while (beanName.startsWith(BeanFactory.FACTORY_BEAN_PREFIX));
return beanName;
});
}
canonicalName(name)
canonicalName(name) 是 org.springframework.core.SimpleAliasRegistry#canonicalName(String) 方法: 获取name的最终别名或者是全类名,通过递归形式在aliasMap【别名映射到规范名称集合】中得到最终的规范名称
/**
* Determine the raw name, resolving aliases to canonical names.
* <p>确定原始名称,将别名解析为规范名称</p>
* @param name the user-specified name - 用户指定的名称
* @return the transformed name - 转换后的名称
*/
public String canonicalName(String name) {
//规范名称初始化化传入的name
String canonicalName = name;
// Handle aliasing... 处理别名
String resolvedName;
//从下面代码可以看出,aliasMap的存储形式是:
// C是真正的规范名称,A,B都是别名:
// aliasMap={key:A,val:B;key:B,val:C},通过A拿到B,再通过B拿到C
do {
//通过 规范名称 从 aliasMap中获取解析后的名称
resolvedName = this.aliasMap.get(canonicalName);
//如果找到了解析后的名称
if (resolvedName != null) {
//规范名称重新赋值为解析后名称
canonicalName = resolvedName;
}
}
//只要找到了解析后的名称
while (resolvedName != null);
return canonicalName;
}
aliasMap 是 org.springframework.core.SimpleAliasRegistry 的成员变量
/**
* Map from alias to canonical name.
* <p>从别名映射到规范名称</p>
* */
private final Map<String, String> aliasMap = new ConcurrentHashMap<>(16);
整个Map数据结构应该要抽象理解为一个二维数组,因为在检索别名的时候,是可以通过别名查别名的
举个栗子:
- A是B的别名,C是B的别名,存放到aliasMap中的数据结构就是:[{key=B,val=A},{key=C,val=B}]
- 当要获取A的所有别名[B,C]时:先获取A的Key->B,则通过递归形式获取B的key->C
getSingleton
获取以beanName注册的(原始)单例对象,该代码的所呈现的三级缓存其实是为解决循环依赖问题,有关循环依赖的资料建议还是看视频,比较好理解,这里不作概述。
- 从单例对象的高速缓存【singletonObjects】中获取beanName的单例对象,赋值为【singletonObject】
- 如果单例对象没成功获取,并且 baneName 是正在被创建:
- 同步,以singletonObjects作为锁
- 从早期单例对象的高速缓存【earlySingletonObjects】中获取bean对象,赋值为【singletonObject】
- 如果singletonObject为null,且允许创建早期引用:
- 从单例工厂的缓存【singletonFactories】中获取beanName的单例工厂对象,赋值给【singletonFactory】
- 如果singletonFactory不为null:
- 从singletonFactory中获取该beanName的单例对象,作为singletonObject
- 添加beanName和singletonObject到 早期单例对象高速缓存【earlySingletonObjects】中
- 从单例对象工厂缓存【singletonFactories】中移除beanName的单例对象工
- 返回singletonObject
/**
* 获取beanName的单例对象,并允许创建早期引用
* @param beanName the name of the bean to look for - 要寻找的bean名
* @see #getSingleton(String, boolean)
*/
@Override
@Nullable
public Object getSingleton(String beanName) {
//获取beanName的单例对象,并允许创建早期引用
return getSingleton(beanName, true);
}
/**
* Return the (raw) singleton object registered under the given name.
* <p>返回以给定名称注册的(原始)单例对象,如果单例对象没有找到,并且beanName存在
* 正在创建的Set集合中</p>
* <p>Checks already instantiated singletons and also allows for an early
* reference to a currently created singleton (resolving a circular reference).
* <p>检查已经实例化的单例,并且还允许对当前的单例的早期引用(解析循环引用)</p>
* @param beanName the name of the bean to look for - 要寻找的bean名
* @param allowEarlyReference whether early references should be created or not
* - 是否应创建早期引用
* @return the registered singleton object, or {@code null} if none found
* - 注册的单例对象;如果找不到,则为{@code null}
*/
@Nullable
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
//从单例对象的高速缓存中获取beanName的单例对象
Object singletonObject = this.singletonObjects.get(beanName);
//如果单例对象没有找到,并且 baneName 是正在被创建
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
//同步,以singletonObjects作为锁
synchronized (this.singletonObjects) {
//从早期单例对象的高速缓存中获取bean对象
singletonObject = this.earlySingletonObjects.get(beanName);
//如果获取不了bean的单例对象,且允许创建早期引用
if (singletonObject == null && allowEarlyReference) {
//从单例工厂的缓存中获取beanName的单例工厂对象
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
//如果beanName的单例工厂对象找到了
if (singletonFactory != null) {
//从beanName的单例工厂对象中获取该beanName的单例对象
singletonObject = singletonFactory.getObject();
//下面的操作主要是为了防止beanName对应的对象重复构建
//添加beanName和其对应的beanName单例对象到 早期单例对象高速缓存中
this.earlySingletonObjects.put(beanName, singletonObject);
//从单例对象工厂缓存中移除beanName的单例对象工厂
this.singletonFactories.remove(beanName);
}
}
}
}
//返回beanName对应的单例对象
return singletonObject;
}
singletonObjects, earlySingletonObjects, singletonFactories 是 org.springframework.beans.factory.support.DefaultSingletonBeanRegistry 的成员变量
/**
* Cache of singleton objects: bean name to bean instance.
* <p>单例对象的高速缓存:beam名称-bean实例,所有bean对象最终都会放到对象中</p>
* */
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
/**
* Cache of singleton factories: bean name to ObjectFactory.
* <p>单例工厂的缓存:bean名称 - ObjectFactory </p>
* */
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);
/**
* Cache of early singleton objects: bean name to bean instance.
* <p>早期单例对象的高速缓存:bean名称 - bean实例</p>
* <p>当从singletonFactories中获取到对应对象后,就会放到这个缓存中</p>
* */
private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);
getObjectForBeanInstance(sharedInstance, name, beanName, null);
从 beanInstannce 中获取公开的Bean对象,主要处理beanInstance是FactoryBean对象的情况,如果不是FactoryBean会直接 返回beanInstance实例
isPrototypeCurrentlyInCreation(beanName)
返回指定的原型bean是否当前正在创建中(在当前线程内)
/**
* Names of beans that are currently in creation.
* <p>当前正在创建的bean名称</p>
* */
private final ThreadLocal<Object> prototypesCurrentlyInCreation =
new NamedThreadLocal<>("Prototype beans currently in creation");
/**
* Return whether the specified prototype bean is currently in creation
* (within the current thread).
* <p>返回指定的原型bean是否当前正在创建中(在当前线程内)</p>
* @param beanName the name of the bean - bean名
*/
protected boolean isPrototypeCurrentlyInCreation(String beanName) {
//获取当前正在创建的bean名称【线程本地】
Object curVal = this.prototypesCurrentlyInCreation.get();
//如果当前正在创建的bean名称不为null,且 (当前正在创建的bean名称等于beanName 或者
// 当前正在创建的bean名称是Set集合,并包含该beanName)
//就返回true,表示在当前线程内,beanName当前正在创建中。
return (curVal != null &&
(curVal.equals(beanName) || (curVal instanceof Set && ((Set<?>) curVal).contains(beanName))));
}