容器Bean实例化
上一节有提到过,在容器准备完成之后,初始化剩下所有的单例Bean(非延迟加载的) 。
finishBeanFactoryInitialization(beanFactory),查看源码可以知道,获取容器中所有的beanName依次调用AbstractBeanFactory#getBean(String name)
方法触发Bean的实例化。
getBean
// AbstractBeanFactory.java
@Override
public Object getBean(String name) throws BeansException {
return doGetBean(name, null, null, false);
}
内部调用 doGetBean(String name, final Class requiredType, Object[] args, boolean typeCheckOnly)
方法,其接受四个方法参数:
name
:要获取 Bean 的名字requiredType
:要获取 bean 的类型args
:创建 Bean 时传递的参数。这个参数仅限于创建 Bean 时使用。typeCheckOnly
:是否为类型检查。
doGetBean
protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
// 1. 根据指定的名称获取获取被管理Bean的名称,剥离指定名称中对容器的相关依赖
// 如果指定的是别名,则将别名转换为规范的Bean名称
final String beanName = transformedBeanName(name);
Object bean;
// 2. 先从缓存中读取是否有已经被创建过的单例模式的Bean, 对于单例模式的Bean, 整个IOC容器中只创建一次
// Eagerly check singleton cache for manually registered singletons.
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
if (logger.isTraceEnabled()) {
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 + "'");
}
}
// 3. 完成 FactoryBean 的相关处理,并用来获取 FactoryBean 的处理结果
// 注意:BeanFactory是管理Bean的工厂, FactoryBean是创建对象的工厂Bean, 两者之间有区别
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
else {
// 运行到这里, 说明缓存中没有我们想要的Bean
// Fail if we're already creating this bean instance:
// We're assumably within a circular reference.
// 4. 因为 Spring 只解决单例模式下的循环依赖, 所以在原型模式下如果存在循环依赖则会抛出异常
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
// 5. 获取当前容器的父容器
// Check if bean definition exists in this factory.
BeanFactory parentBeanFactory = getParentBeanFactory();
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
// Not found -> check parent.
// 解析指定Bean名称的原始名称
String nameToLookup = originalBeanName(name);
// 父类容器为 AbstractBeanFactory, 直接递归查找
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 if (requiredType != null) {
// No args -> delegate to standard getBean method.
return parentBeanFactory.getBean(nameToLookup, requiredType);
}
else {
return (T) parentBeanFactory.getBean(nameToLookup);
}
}
// 6. 创建的Bean是否需要进行类型验证
if (!typeCheckOnly) {
// 如果不需要, 将指定的bean标记为已经创建(或即将创建)
markBeanAsCreated(beanName);
}
try {
// 7. 从容器中获取 beanName 相应的 BeanDefinition 对象
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);
// 8. 处理所依赖的Bean
// 每个 bean 都不是单独工作的,它会依赖其他 bean,其他 bean 也会依赖它,对于依赖的 bean ,它会优先加载,所以在 Spring 的加载顺序中,在初始化某一个 bean 的时候首先会初始化这个 bean 的依赖。
// Guarantee initialization of beans that the current bean depends on.
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
// 当前Bean有依赖的Bean
for (String dep : dependsOn) {
// 循环依赖的情况
if (isDependent(beanName, dep)) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
}
// 把被依赖的Bean注册给当前的Bean
registerDependentBean(dep, beanName);
try {
// 递归调用getBean方法,实例化当前Bean所依赖的Bean
getBean(dep);
}
catch (NoSuchBeanDefinitionException ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"'" + beanName + "' depends on missing bean '" + dep + "'", ex);
}
}
}
// 9. 实例化Bean
// Create bean instance.
if (mbd.isSingleton()) { // 单例模式
// 这里使用一个匿名内部类创建Bean实例对象
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.
// 显式从单例缓存中删除 Bean 实例
destroySingleton(beanName);
throw ex;
}
});
// 获取Bean的实例对象
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
else if (mbd.isPrototype()) { // 原型模式
// It's a prototype -> create a new instance.
// 原型模式每次都会创建一个新的对象
Object prototypeInstance = null;
try {
// 记录当前创建的原型对象
beforePrototypeCreation(beanName);
// 创建Bean
prototypeInstance = createBean(beanName, mbd, args);
}
finally {
// beforePrototypeCreation 记录了当前创建的原型对象, 此时需要移除
afterPrototypeCreation(beanName);
}
// 获取Bean的实例对象
bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
}
else {
// 要创建的Bean既不是单例模式的也不是原型模式的
// 这种方式在Web应用程序中比较常用, 如request、session、application等生命周期
String scopeName = mbd.getScope();
final Scope scope = this.scopes.get(scopeName);
// 如果Bean定义资源中没有配置生命周期范围, 则Bean定义不合法
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的实例对象
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;
}
}
// 10. 检查需要的类型是否符合 bean 的实际类型
// 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.isTraceEnabled()) {
logger.trace("Failed to convert bean '" + name + "' to required type '" +
ClassUtils.getQualifiedName(requiredType) + "'", ex);
}
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
}
}
return (T) bean;
}
获取beanName
// AbstractBeanFactory.java
// 根据指定的名称获取获取被管理Bean的名称,剥离指定名称中对容器的相关依赖
// 如果指定的是别名,则将别名转换为规范的Bean名称
final String beanName = transformedBeanName(name);
这里的name不一定就是beanName,有可能是bean的别名,也有可能是 FactoryBean ,所以这里通过 transformedBeanName(String name)
方法对 name
进行转换
// AbstractBeanFactory.java
protected String transformedBeanName(String name) {
return canonicalName(BeanFactoryUtils.transformedBeanName(name));
}
调用 BeanFactoryUtils#transformedBeanName(String name)
方法,是为了去除 FactoryBean 的修饰符 ,如果 name 以 “&” 为前缀,那么会去掉该 “&”,例如,name = "&studentService"
,则会是 beanName = "studentService"
。
// BeanFactoryUtils.java
public static String transformedBeanName(String name) {
Assert.notNull(name, "'name' must not be null");
// BeanFactory.FACTORY_BEAN_PREFIX = "&";
if (!name.startsWith(BeanFactory.FACTORY_BEAN_PREFIX)) {
return name;
}
// computeIfAbsent 方法,分成两种情况:
// 1. name未存在,则进行计算执行,并将结果添加到缓存
// 2. name已存在,则直接返回。
return transformedBeanNameCache.computeIfAbsent(name, beanName -> {
do {
beanName = beanName.substring(BeanFactory.FACTORY_BEAN_PREFIX.length());
}
while (beanName.startsWith(BeanFactory.FACTORY_BEAN_PREFIX));
return beanName;
});
}
transformedBeanNameCache主要是用来缓存name转换后的beanName,下次获取相同的name时可以直接从缓存中获取。
public String canonicalName(String name) {
String canonicalName = name;
String resolvedName;
do {
resolvedName = (String)this.aliasMap.get(canonicalName);
if (resolvedName != null) {
canonicalName = resolvedName;
}
} while(resolvedName != null);
return canonicalName;
}
主要是一个循环获取 beanName 的过程,例如,别名 A 指向名称为 B 的 bean 则返回 B,若 别名 A 指向别名 B,别名 B 指向名称为 C 的 bean,则返回 C。