本文我们来了解下 spring 中 BeanDefinition 的注册
在 spring 中对 bean 的注册主要有两种方式:
- 第一种是通过配置来注册我们的bean,对应的方法是 DefaultListableBeanFactory 里的 registerBeanDefinition() 方法
- 第二种是直接注册一个单例 bean,对应的方法则是 DefaultListableBeanFactory 里的 registerSingleton() 方法
下面我们分别来看看这两个方法
registerBeanDefinition()
首先是我们的 registerBeanDefinition() 方法
@Override
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
throws BeanDefinitionStoreException {
((AbstractBeanDefinition) beanDefinition).validate();
BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName);
if (existingDefinition != null) {
this.beanDefinitionMap.put(beanName, beanDefinition);
}
else {
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 {
synchronized (this.singletonObjects) {
Object oldObject = this.singletonObjects.get(beanName);
if (oldObject != null) {
throw new IllegalStateException("Could not register object [" + singletonObject +
"] under bean name '" + beanName + "': there is already object [" + oldObject + "] bound");
}
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;
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
else {
}
return (T) bean;
}
我们大概能看出,我们在 getBean() 操作时,会有以下几个步骤
- 先去查找 Singleton bean ,如果找到则直接返回
- 若找不到,则去 BeanDefinition 中找,如果找到则将它变成 bean 对象,激活其生命周期,然后返回
总结
本文只是对 beanDefinition 注册相关的一些简单的分析,其中值得关注的是两种 bean 的注册方式:通过配置 bean 和直接注册 singleton bean,还有就是对 bean 的查找的简单分析:先去查单例 bean,找到可以直接返回,找不到的话再去查 BeanDefinition, 若找到了,则直接将其变成 bean,同时激活其生命周期,然后返回。
|