Spring 中 BeanDefinition 的注册

本文详细介绍了Spring中BeanDefinition的注册,包括registerBeanDefinition()和registerSingleton()方法,以及getBean()的简单介绍。讨论了如何通过配置注册bean,注册单例bean的过程,并概述了bean查找的步骤。

本文我们来了解下 springBeanDefinition 的注册

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,同时激活其生命周期,然后返回。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值