Spring源码解析之【BeanFactory】与【BeanDefinitionRegistry】

Spring源码解析之【BeanFactory】与【BeanDefinitionRegistry】

Posted by guyang on March 17, 2022

Spring源码解析之【BeanFactory】与【BeanDefinitionRegistry】

Spring的一个非常重要的概念的就是Bean,Spring容器需要通过扫描和注册来实现对Bean信息的管理。在分析了Spring的源码之后发现,Spring里面用了很多的BeanFactory,这个类非常重要,因为实际上在Spring中BeanFactory是IOC容器的实际代表者,它用来创建和管理Bean。它为其他具体的IOC容器提供了最基本的规范,它是一个接口类型。

BeanFactory是最典型的工厂方法模式。不同类型的工厂会生产不同类型的商品。它的子接口和对应的实现类结构如下:

1647506137913

我们可以看到在BeanFactory接口下面有三个子接口:

  • HierarchicalBeanFactory:提供父容器的访问功能
    • ConfigurableBeanFactory 接口
  • AutowireCapableBeanFactory:在BeanFactory基础上是实现了对已存在实例的管理

  • ListableBeanFactory:提供了批量获取Bean的方法

接口ConfigurableListableBeanFactory继承了上述的三个接口,增加了一些其他的功能:如类加载器、类型转换,属性编辑器,BeanPostProcessor,Bean定义等

实现类DefaultListableBeanFactory继承ConfigurableListableBeanFactory接口,实现了所有的BeanFactory功能,且可以注册BeanDefinition。

1.1 ListableBeanFactory接口

上面的第一个图片没有截全,遗漏了ListableBeanFactory的部分实现类信息,且这个实现类还比较重要,因此再增加一个图片。

1647506386032

我们可以看到AnnotataionConfigApplicationContext实现了ListableBeanFactory接口。AnnotataionConfigApplicationContext类是注解驱动去扫描Bean的定义信息。这个类我们很熟悉,因为在Spring启动的时候就是利用这个类:

1
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class);

在使用BeanFactory工厂创建Bean的过程中,我们需要利用BeanDefinitionRegistry将这些Bean注册到DefaultListableBeanFactory中。那么接下来就介绍一下BeanDefinitionRegistry

2. BeanDefinitionRegistry接口

1
2
3
public interface BeanDefinitionRegistry extends AliasRegistry{
    
}

从上述代码可以看出,BeanDefinitionRegistry接口实现了AliasRegistry接口,它主要的工作就是定义Bean的常规操作。

它有三个子接口:

  • SimpleBeanDefinitionRegistry实现类

  • DefaultListableBeanFactory 实现类

    • 基本实现类 ,拥有registryBeanDefinition功能
  • GenericApplicationContext实现类

1647506586856

2.1 BeanDefinitionRegistry接口的功能

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public interface BeanDefinitionRegistry extends AliasRegistry {

	// 向beanFactory中注册一个BeanDefinition
	void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
			throws BeanDefinitionStoreException;

	// 根据beanName从beanFactory中移除一个已经注册的BeanDefinition
	void removeBeanDefinition(String beanName) throws NoSuchBeanDefinitionException;

	// 根据beanName从beanFactory中获取一个BeanDefinition
	BeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException;

	// 判断beanFactory中是否有beanName的BeanDefinition
	boolean containsBeanDefinition(String beanName);

	// 获取beanFactory中的所有BeanDefinition的beanName
	String[] getBeanDefinitionNames();

	// 获取beanFactory中的BeanDefinition的数量
	int getBeanDefinitionCount();

	// 判断beanFactory中的beanName是否被占用
	boolean isBeanNameInUse(String beanName);
}

2.2 SimpleBeanDefinitionRegistry

BeanDefinitionRegistry的一个简单实现方式,没有内置的beanFactory,这个类是用来留给我们测试用的。开发情况下Spring不会使用该类。 这个类的功能很简单,这里就不做详细介绍了,根据方法的名称就可以看出对应的方法所实现的功能。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
public class SimpleBeanDefinitionRegistry extends SimpleAliasRegistry implements BeanDefinitionRegistry {

	// 使用ConcurrentHashMap来存储beanName和BeanDefinition
	private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(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);
	}

	@Override
	public void removeBeanDefinition(String beanName) throws NoSuchBeanDefinitionException {
		if (this.beanDefinitionMap.remove(beanName) == null) {
			throw new NoSuchBeanDefinitionException(beanName);
		}
	}

	@Override
	public BeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException {
		BeanDefinition bd = this.beanDefinitionMap.get(beanName);
		if (bd == null) {
			throw new NoSuchBeanDefinitionException(beanName);
		}
		return bd;
	}

	@Override
	public boolean containsBeanDefinition(String beanName) {
		return this.beanDefinitionMap.containsKey(beanName);
	}

	@Override
	public String[] getBeanDefinitionNames() {
		return StringUtils.toStringArray(this.beanDefinitionMap.keySet());
	}

	@Override
	public int getBeanDefinitionCount() {
		return this.beanDefinitionMap.size();
	}

	@Override
	public boolean isBeanNameInUse(String beanName) {
		return isAlias(beanName) || containsBeanDefinition(beanName);
	}
}

2.3 DefaultListableBeanFactory

这个类非常重要,它是BeanDefinitionResgitry接口的基本实现,实际上很多beanFactory最后都是调用DefaultListableBeanFactory类的 registerBeanDefinition 来注册beanDefinition.

这个类里面有非常多的方法,这里只介绍比较重要的 registerBeanDefinition 方法的实现。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory
		implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable {
    
    // 以Map的数据结构保存beanName和BeanDefinition
	private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);
    // 保存所有beanDefinition的名字
	private volatile List<String> beanDefinitionNames = new ArrayList<>(256);
    
    // 注册BeanDefinition的信息
    @Override
	public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
			throws BeanDefinitionStoreException {

		Assert.hasText(beanName, "Bean name must not be empty");
		Assert.notNull(beanDefinition, "BeanDefinition must not be null");

		if (beanDefinition instanceof AbstractBeanDefinition) {
			try {
				((AbstractBeanDefinition) beanDefinition).validate();
			}
			catch (BeanDefinitionValidationException ex) {
				throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
						"Validation of bean definition failed", ex);
			}
		}
		// 先判断当前的beanName对应的bean信息是否已经存在
		BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName);
		if (existingDefinition != null) {
            // 是否允许覆盖
			if (!isAllowBeanDefinitionOverriding()) {
				throw new BeanDefinitionOverrideException(beanName, beanDefinition, existingDefinition);
			}
            // 若允许覆盖  那还得比较下role  如果新进来的这个Bean的role更大	
			else if (existingDefinition.getRole() < beanDefinition.getRole()) {
				//...
			}
			else if (!beanDefinition.equals(existingDefinition)) {
				//...
			}
			else {
				//...
			}
			this.beanDefinitionMap.put(beanName, beanDefinition);
		}
		else {
			if (hasBeanCreationStarted()) {
				// hasBeanCreationStarted:说明已经存在bean已经在创建了
				synchronized (this.beanDefinitionMap) {
                    // 将beanName和beanDefinition放进去
					this.beanDefinitionMap.put(beanName, beanDefinition);
					List<String> updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1);
					updatedDefinitions.addAll(this.beanDefinitionNames);
					updatedDefinitions.add(beanName);
					this.beanDefinitionNames = updatedDefinitions;
					removeManualSingletonName(beanName);
				}
			}
			else {
				// 仍然处在Spring启动阶段
				this.beanDefinitionMap.put(beanName, beanDefinition);
				this.beanDefinitionNames.add(beanName);
				removeManualSingletonName(beanName);
			}
			this.frozenBeanDefinitionNames = null;
		}

		if (existingDefinition != null || containsSingleton(beanName)) {
			resetBeanDefinition(beanName);
		}
		else if (isConfigurationFrozen()) {
			clearByTypeCache();
		}
	}    
} 

2.4AnnotationConfigApplicationContext

这个类是GenericApplicationContext的子类,但是通过分析这个类的方法,发现并没有registryBeanDefinition方法。

1647507505235

虽然没有registryBeanDefinition方法,但是又register方法,而register方法又调用了AnnotatedBeanDefinitionReader类的register方法,经过一系列的操作,最后调用了DefaultListableBeanFactory类的registerBeanDefinition 方法。

3 总结

  1. Spring使用BeanFactory作为创建Bean的工厂,利用BeanDefinitionRegistry来注册BeanDefinition,实际上都是使用DefaultListableBeanFactory类的registerBeanDefinition