【手写Spring框架】 Bean构造器的实现——BeanDefinition和BeanDefinitionRegistry 简易版复现

103 阅读2分钟

Spring Bean构建

代码仓库参考:github.com/DerekYRC/mi…

Bean的最终目标是什么呢??

应该是获取一个指定beanName和指定BeanDefinitionBean对象,这个对象还最好是Singleton的单例类型!

那好,现在我们要实现三个接口特点,单例(Singleton)、Bean实体(Bean)和Bean类型(BeanDefinition)

现在我们分为两大步进行拆解

1. 实现Bean构造器

1.1 创建Singleton Bean

image.png

  • 接口

    • SingletionBeanRegistry 根据beanName 获取SingletonBean
    • BeanFactory 根据beanName 获取Bean
    • DefaultSingletonBeanRegistry 添加和获取SingletonBean
    • AbstractBeanFactory 创建和获取SingletonBean (利用BeanFactorygetBean接口)
    • AbstractAutowireCapableBeanFactor 创建BeanDefition类型的SingleBean
  • 抽象类

    • AbstractBeanFactory 创建Bean对象(createBeanAbstractAutowireCapableBeanFactory实现),获取BeanDefinition

public interface BeanFactory {

	/**
	 * 获取bean
	 *
	 * @param name
	 * @return
	 * @throws BeansException bean不存在时
	 */
	Object getBean(String name) throws BeansException;
}

public abstract class AbstractBeanFactory extends DefaultSingletonBeanRegistry implements BeanFactory {

	@Override
	public Object getBean(String name) throws BeansException {
		Object bean = getSingleton(name);
		// 获取到Bean,返回相应的Bean
		if (bean != null) {
			return bean;
		}
		// 没有获取到相应的bean,重新定义一个Bean,注入到
		BeanDefinition beanDefinition = getBeanDefinition(name);
		return createBean(name, beanDefinition);
	}
 }

1.2 创建Definition 类型的Singleton Bean

Spring Bean复现简易版继承关系图

  • 接口

    • BeanDefinitionRegistry 根据beanName 向注册表中注册Bean

BeanDefinitionRegistry接口和AbstractBeanFactory结合起来,至此,实现了一个基本的兼具三个接口能力的Bean构造器,能够根据指定的beanNameBeanDefinition进行相应的Singleton类型的Bean构造。

下图是Bean构造器DefaultListableBeanFactory的类关系图

Bean创建简易版.png

Amazing ,那接下来是不是得试下,这玩意能不能用?

2.测试Bean构造器

Bean 构造器创建新的Bean类型是如何处理的

下面测试使用DefaultListableBeanFactory创建新的HelloService 类型的Bean

@Test
public void testCreateSingletonBean(){
   DefaultListableBeanFactory defaultListableBeanFactory = new DefaultListableBeanFactory();
   BeanDefinition beanDefinition = new BeanDefinition(HelloService.class);
   defaultListableBeanFactory.registerBeanDefinition("helloservice",beanDefinition);
   HelloService helloservice = (HelloService)defaultListableBeanFactory.getBean("helloservice");
   Assert.assertNotNull(helloservice);
}

第5和6行分别使用端点调试的方法

image.png

先说结论: 根据beanDefinition向注册表里添加Bean类型和创建实例化Bean是分开的

添加Bean类型

BeanDefinitionRegistry通过接口BeanDefinitionRegistrybeanDefinitionMap也就是Bean的注册表里添加新的Bean类型,此时没有创建SingletonBean示例

image.png

实例化Bean类型

DefaultListableBeanFactory 获取Bean实例,继承BeanFactory的接口,获取beanName为helloservice的Bean实例,singletonObjects是空的呀,自然是获取不到呢。哈哈哈哈 这个时候,就需要正式的注入一个beanName为"helloservice"的Bean实例啦!

image.png

AbstractAutowireCapableBeanFactory正式登场!!

image.png

addSingleton正好是继承了DefaultSingletonBeanRegistry类,正好加上了一个Singleton的Bean类型,完美!一切都是刚刚好!

image.png

乍看起来,感觉搞了好多类,一定会有剩余无用的东西,但是每一个设计的都恰到好处,这就是Spring优秀开源框架的魅力吧

下面再简单看下创建新的Bean的流程。

image.png

*号表示对接口或者protected函数的继承实现