spring 源码系列(一)- BeanDefinition及注册

1 BeanDefinition介绍

1.1 BeanDefinition

关于BeanDefinition介绍部分,参考自知乎的大神bravo1988,链接:https://www.zhihu.com/answer/723146648

BeanDeifinition实际上是生成bean之前的中间态,”假设Bean是红烧肉,那BeanDefinition就是该怎么做红烧肉“,也就是说,BeanDeifinition定义的是如何实例化bean这个过程。

BeanDefinition内部定义许多属性,但最常用实际上就下面几个:

  1. 懒加载:该bean是否实现懒加载?
  2. 单例/多例:该bean是单例还是多例?
  3. 初始化、销毁方法:定义该bean的初始化和销毁方法。
1.2 AnnotatedBeanDefinition

AnnotatedBeanDefinition是BeanDefinition的子接口,在Definition定义了bean的一些基本属性的基础上,还定义了两个Metadata:AnnotationMetadata和MethodMetadata

public interface AnnotatedBeanDefinition extends BeanDefinition {
	AnnotationMetadata getMetadata();

	MethodMetadata getFactoryMethodMetadata();
}

MetaData称为元数据,指的是数据的数据,包括类名,方法名,注释名等等,详情请见我的博客:spring 之 元数据metadata:https://blog.csdn.net/bintoYu/article/details/104291098

2 BeanDefinition的注册

spring在初始化的过程中,会将BeanDefinition注册到内部中,下面会对其中的几个相关类进行介绍:

2.1 BeanDefinitionRegistry

BeanDefinitionRegistry是BeanDefinition的注册接口,也可以认为是BeanDefinition的存储接口,该接口定义了BeanDefinition的注册(增)、移除(删)、获得(查)的功能。

public interface BeanDefinitionRegistry extends AliasRegistry {

	void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
			throws BeanDefinitionStoreException;

	void removeBeanDefinition(String beanName) throws NoSuchBeanDefinitionException;

	BeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException;

	boolean containsBeanDefinition(String beanName);

	String[] getBeanDefinitionNames();

	int getBeanDefinitionCount();

	boolean isBeanNameInUse(String beanName);

}
2.2 SimpleBeanDefinitionRegistry

SimpleBeanDefinitionRegistry是BeanDefinitionRegistry的一个简单的实现类,使用名为beanDefinitionMap 的beanDefinitionMap来对BeanDefinition进行管理,但实际上很少会用到。

public class SimpleBeanDefinitionRegistry extends SimpleAliasRegistry implements BeanDefinitionRegistry {

	private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<String, BeanDefinition>(64);

	@Override
	public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
			throws BeanDefinitionStoreException {
		Assert.hasText(beanName, "'beanName' must not be empty");
		Assert.notNull(beanDefinition, "BeanDefinition must not be null");
		this.beanDefinitionMap.put(beanName, beanDefinition);
	}

	...
2.3 DefaultListableBeanFactory

DefaultListableBeanFactory是最常用的BeanFactory,该类贯穿着整个spring体系中,有着许多的功能,其中一个就是对BeanDefinition进行管理,该类也实现了BeanDefinitionRegistry接口,本文只介绍与BeanDefinition相关的部分:

public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory
		implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable {
	//也以beanDefinitionMap作为容器
	private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<String, BeanDefinition>(256);
	//按照注册顺序存放名称
	private volatile List<String> beanDefinitionNames = new ArrayList<String>(256);

	@Override
	public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
			throws BeanDefinitionStoreException {

		...进行一些判断

		BeanDefinition oldBeanDefinition;
		oldBeanDefinition = this.beanDefinitionMap.get(beanName);
		
		// 如果旧的不为null,说明这个beanName对应BeanDefinition已经存在
		if (oldBeanDefinition != null) {
			//判断是否允许覆盖(默认允许)
			if (!isAllowBeanDefinitionOverriding()) {
				//抛异常
			}
			// 若允许覆盖  那还得比较下role  如果新进来的这个Bean的role更大			
			// 比如老的是ROLE_APPLICATION:0  新的是ROLE_INFRASTRUCTURE:2
			else if (oldBeanDefinition.getRole() < beanDefinition.getRole()) {
				//打印一个warn日志提醒一下
			}
			...
			//最终会将旧的替换掉
			this.beanDefinitionMap.put(beanName, beanDefinition);
		}
		else {
			//如果bean的创建阶段已经结束了,那么非线程安全的beanDefinitionNames和manualSingletonNames的处理方式便会有所不同,不是很重要
			if (hasBeanCreationStarted()) {
				//加个线程锁
				synchronized (this.beanDefinitionMap) {
					//添加到beanDefinitionMap和manualSingletonNames中
					this.beanDefinitionMap.put(beanName, beanDefinition);
					List<String> updatedDefinitions = new ArrayList<String>(this.beanDefinitionNames.size() + 1);
					updatedDefinitions.addAll(this.beanDefinitionNames);
					updatedDefinitions.add(beanName);
					this.beanDefinitionNames = updatedDefinitions;
					//manualSingletonNames移除该bean,不是很重要
					if (this.manualSingletonNames.contains(beanName)) {
						Set<String> updatedSingletons = new LinkedHashSet<String>(this.manualSingletonNames);
						updatedSingletons.remove(beanName);
						this.manualSingletonNames = updatedSingletons;
					}
				}
			}
			else {
				this.beanDefinitionMap.put(beanName, beanDefinition);
				this.beanDefinitionNames.add(beanName);
				this.manualSingletonNames.remove(beanName);
			}
			this.frozenBeanDefinitionNames = null;
		}

		if (oldBeanDefinition != null || containsSingleton(beanName)) {
			resetBeanDefinition(beanName);
		}
	}
	
	@Override
	public void removeBeanDefinition(String beanName) throws 		NoSuchBeanDefinitionException {
		// 移除整体上比较简单:beanDefinitionMap.remove

		//从beanDefinitionMap中移除
		BeanDefinition bd = this.beanDefinitionMap.remove(beanName);
		// 若这个Bean定义本来就不存在,需要抛异常
		if (bd == null) {
			throw new NoSuchBeanDefinitionException(beanName);
		}
		
		//从beanDefinitionNames中移除
		if (hasBeanCreationStarted()) {
			synchronized (this.beanDefinitionMap) {
				List<String> updatedDefinitions = new ArrayList<>(this.beanDefinitionNames);
				updatedDefinitions.remove(beanName);
				this.beanDefinitionNames = updatedDefinitions;
			}
		} else {
			this.beanDefinitionNames.remove(beanName);
		}
		
		this.frozenBeanDefinitionNames = null;
		resetBeanDefinition(beanName);
	}

	// 这个实现非常的简单,直接从map里拿
	@Override
	public BeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException {
		BeanDefinition bd = this.beanDefinitionMap.get(beanName);
		if (bd == null) {
			throw new NoSuchBeanDefinitionException(beanName);
		}
		return bd;
	}

}
2.4 GenericApplicationContext

BeanDefinitionRegistry真的是一个很神奇的接口,不仅作为BeanFactory的DefaultListableBeanFactory实现了它,作为spring容器ApplicationContext的GenericApplicationContext也实现了它。

实际上GenericApplicationContext并没有去重写BeanDefinitionRegistry的方法,而是内置了一个DefaultListableBeanFactory,借用DefaultListableBeanFactory来管理BeanDefinition。(有点适配器模式的味道,但应该不是适配器模式)

public class GenericApplicationContext extends AbstractApplicationContext implements BeanDefinitionRegistry {
	//内置了一个DefaultListableBeanFactory
	private final DefaultListableBeanFactory beanFactory;
	
	@Override
	public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
			throws BeanDefinitionStoreException {

		this.beanFactory.registerBeanDefinition(beanName, beanDefinition);
	}

	@Override
	public void removeBeanDefinition(String beanName) throws NoSuchBeanDefinitionException {
		this.beanFactory.removeBeanDefinition(beanName);
	}

	@Override
	public BeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException {
		return this.beanFactory.getBeanDefinition(beanName);
	}
}
2.5 AnnotationConfigApplicationContext

从类的声明上看,AnnotationConfigApplicationContext似乎并不属于BeanDefinitionRegistry接口:

public class AnnotationConfigApplicationContext extends GenericApplicationContext implements AnnotationConfigRegistry 

但实际上,我们看到AnnotationConfigApplicationContext继承了GenericApplicationContext,根据java的规范,子类是会继承父类的所有方法的,也就是说,Java中子类会继承父类对于接口的实现。
因此AnnotationConfigApplicationContext也能用于管理BeanDefinition。
至于为什么要讲到这个类,其实是为了给我的另一篇博客”spring 之 AnnotationConfigApplicationContext“提供帮助。

参考

怎么回答面试官:你对Spring的理解?
【小家Spring】Spring的Bean定义注册中心BeanDefinitionRegistry详解

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值