本文我们来了解下 spring 中 BeanDefinition 的注册
在 spring 中对 bean 的注册主要有两种方式:
- 第一种是通过配置来注册我们的bean,对应的方法是 DefaultListableBeanFactory 里的 registerBeanDefinition() 方法
- 第二种是直接注册一个单例 bean,对应的方法则是 DefaultListableBeanFactory 里的 registerSingleton() 方法
下面我们分别来看看这两个方法
registerBeanDefinition()
首先是我们的 registerBeanDefinition() 方法
@Override
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
throws BeanDefinitionStoreException {
/* 对 beanDefinition 进行校验 */
((AbstractBeanDefinition) beanDefinition).validate();
/* 首先去 map 中(也可以理解为缓存)去查找 beanDefinition */
BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName);
/* 如果找到的 beanDefinition 不为空 */
if (existingDefinition != null) {
/* 这里做了一堆判断,如果都没发生错误(异常)就执行下面语句,重新将它放入到map(缓存)中 */
this.beanDefinitionMap.put(beanName, beanDefinition);
}
/* 为空的情况 */
else {
/* 将其放入到map中,并将该beanDefinition的名字加入到数组(有序)中 */
this.beanDefinitionMap.put(beanName, beanDefinition);
this.beanDefinitionNames.add(beanName);
/* 跟依赖循环相关的缓存,这里暂时先不关注 */
removeManualSingletonName(beanName);
/* 冻结配置相关的代码 */
this.frozenBeanDefinitionNames = null;
}
}
在 registerBeanDefinition() 中,主要逻辑比较简单明了:
- 首先对 beanDefinition 进行校验
- 校验通过后先查询缓存
- 如果缓存中有,则把它覆盖到缓存中
- 如果缓存中没有,将它注册并加入到缓存中,同时将它的名字也加入到数组(有序的,保存着 beanDefinition 的名字)中
registerSingleton()
第二个方法则是直接向beanFactory中注册一个单例bean
@Override
public void registerSingleton(String beanName, Object singletonObject) throws IllegalStateException {
/* 执行到这里后,进入下面的方法 */
super.registerSingleton(beanName, singletonObject);
updateManualSingletonNames(set -> set.add(beanName), set -> !this.beanDefinitionMap.containsKey(beanName));
clearByTypeCache();
}
@Override
public void registerSingleton(String beanName, Object singletonObject) throws IllegalStateException {
/* 这里加锁,保证了注册单例bean时的线程安全 */
synchronized (this.singletonObjects) {
/* 从缓存中查询 */
Object oldObject = this.singletonObjects.get(beanName);
/* 如果查询到对象不为空(也就是说已经存在该bean),抛出一个异常 */
if (oldObject != null) {
throw new IllegalStateException("Could not register object [" + singletonObject +
"] under bean name '" + beanName + "': there is already object [" + oldObject + "] bound");
}
/* 将其加入到 beanFactory 和缓存中 */
addSingleton(beanName, singletonObject);
}
}
registerSingleton() 的逻辑就更加简单了:
- 当执行到 super.registerSingleton(beanName, singletonObject); 这行代码时,调用父类的 registerSingleton() 方法
- 在父类的 registerSingleton() 方法,首先是判断该 bean 是否已经存在,如果存在的话就向外抛异常,若不存在就将它注册并加入到缓存中
getBean() 的简单介绍
当我们的 beanDefinition 注册完后,该如何去找它们?
依赖查找一般情况下会调用 getBean() 方法
getBean() 方法中会调用 doGetBean() 方法
protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
final String beanName = transformedBeanName(name);
Object bean;
/* 首先去查询 singleton 对象 */
Object sharedInstance = getSingleton(beanName);
/* 如果查到对象不为空 */
if (sharedInstance != null && args == null) {
/* 将其复制给bean,然后返回 */
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
/* 如果查到对象为空(单例 bean 中不存在该 bean,去 BeanDefinition 里面去找) */
else {
/*
* 这里我们不对里面的细节探讨,只是简单说明以下流程
* 如果找到该 beanDefinition,将它变成 bean,并激活其生命周期
* 然后返回
*/
}
return (T) bean;
}
我们大概能看出,我们在 getBean() 操作时,会有以下几个步骤
- 先去查找 Singleton bean ,如果找到则直接返回
- 若找不到,则去 BeanDefinition 中找,如果找到则将它变成 bean 对象,激活其生命周期,然后返回
总结
本文只是对 beanDefinition 注册相关的一些简单的分析,其中值得关注的是两种 bean 的注册方式:通过配置 bean 和直接注册 singleton bean,还有就是对 bean 的查找的简单分析:先去查单例 bean,找到可以直接返回,找不到的话再去查 BeanDefinition, 若找到了,则直接将其变成 bean,同时激活其生命周期,然后返回。
本文详细介绍了Spring中BeanDefinition的注册,包括registerBeanDefinition()和registerSingleton()方法,以及getBean()的简单介绍。讨论了如何通过配置注册bean,注册单例bean的过程,并概述了bean查找的步骤。


被折叠的 条评论
为什么被折叠?



