Spring写轮眼计划之初创Bean工厂(一)

前言

Spring写轮眼计划系列是根据自底向上的方式,从最底层的方式开始一步步搭建整个Spring框架,通过造轮子的方式,去了解到Spring最核心的功能是怎么实现的,从而进一步熟悉Spring。
阅读该系列可搭配博主的spring-learn 的源码,进食更顺畅。

环境要求

  • JDK:11+

开整

第一阶段,主要做个能生产bean对象的工厂出来,就像是做个简易的spring ioc出来。

首先,先定义一个描述bean的对象,记录这个bean是代表哪个类的(未来还会加这个bean的作用域什么等等…),就像一个配方一样,工厂根据这个配方可以源源不断地生产出类似的产品,那么他就叫 BeanDefinition :

public class BeanDefinition {

    private Class beanClass;

    public BeanDefinition(Class beanClass) {
        this.beanClass = beanClass;
    }

    public Class getBeanClass() {
        return beanClass;
    }

    public void setBeanClass(Class beanClass) {
        this.beanClass = beanClass;
    }

}

BeanDefinition定义了,那接下来是不是要制定一个存储它的方法,我们姑且叫 注册,于是 BeanDefinitionRegistry 接口便出来了:

public interface BeanDefinitionRegistry {
    /**
	 * 向注册表中注BeanDefinition
	 *
	 * @param beanName
	 * @param beanDefinition
	 */
	void registerBeanDefinition(String beanName, BeanDefinition beanDefinition);
}

那么既然是存储,那存储的数据结构肯定是集合了,而这个集合肯定是某个实际的bean工厂的成员变量了对吧,基于扩展性我们是不能直接做个实际的工厂出来的,我们还是得先制定它最基础的接口工厂。
所以 BeanFactory 便出来了,基础的方法就是 getBean ,客户端想拿某些bean都是通过这个方法来获取 :

public interface BeanFactory {

    Object getBean(String name) throws BeansException;

}

接口工厂出来了, 我们再做个抽象工厂 AbstractBeanFactory, 来实现接口工厂的 getBean,当然因为是抽象工厂,所以存储集合不能放到这里,于是在实现getBean里用了模板方法模式,对外开放 getBean 的入口,然后再把getBean里的  createBeangetBeanDefinition 作为扩展方法开放出去,供高层使用:

public abstract class AbstractBeanFactory implements BeanFactory {

	@Override
	public Object getBean(String name) throws BeansException {
		BeanDefinition beanDefinition = getBeanDefinition(name);
		return createBean(name, beanDefinition);
	}

	protected abstract Object createBean(String beanName, BeanDefinition beanDefinition) throws BeansException;

	protected abstract BeanDefinition getBeanDefinition(String beanName) throws BeansException;
}

那接下来是不是要制定实际bean工厂了呢?理论上是可以这么做的,但spring却没有,它在这之前又加了一个抽象工厂 AbstractAutowireCapableBeanFactory, 主要是干实例化bean的工作:

public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory {

	@Override
	protected Object createBean(String beanName, BeanDefinition beanDefinition) throws BeansException {
		return doCreateBean(beanName, beanDefinition);
	}

	protected Object doCreateBean(String beanName, BeanDefinition beanDefinition) throws BeansException {
		Class beanClass = beanDefinition.getBeanClass();
		Object bean = null;
		try {
			bean = beanClass.newInstance();
		} catch (Exception e) {
			throw new BeansException("实例化bean失败", e);
		}
		return bean;
	}
}

为什么要做多一个 AbstractAutowireCapableBeanFactory呢?spring可能期望的是把个体的职责跟群体的职责拆分开了,你看后面 又做了代表群体性的

DefaultListableBeanFactory, 这样的话群体性的操作都放到这里然后再继承个体的 AbstractAutowireCapableBeanFactory,这样层级就很分明了,对扩展性跟维护性都有极大的提升。
当然,存储集合的家也是这个工厂了,所以我们可以把操作存储集合相关的方法都放到这个工厂里实现了,比如注册到集合里、从集合里获取,集合的数量是多少等等…

public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory implements BeanDefinitionRegistry, ListableBeanFactory {

	private Map<String, BeanDefinition> beanDefinitionMap = new HashMap<>();

	@Override
	public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) {
		beanDefinitionMap.put(beanName, beanDefinition);
	}

	@Override
    protected BeanDefinition getBeanDefinition(String beanName) throws BeansException {
        if (containsBeanDefinition(beanName)) {
			throw new BeansException(String.format("No bean named %s is defined", beanName));
		}
		return beanDefinitionMap.get(beanName);
	}

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

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

这样的话,我们就基本实现了能生产bean对象的工厂的目标,后面我们可以通过DefaultListableBeanFactory去拿到我们期望的bean对象,当然在此之前,我们得先把bean注册上去。基本步骤如下:

  • 先new一个工厂,DefaultListableBeanFactory
  • 往工厂里注册一个期望的对象,工厂就会记录下这个对象的基本信息,或者说配方。
  • 客户端通过工厂的getBean方法,获取到该对象。

测试用例

新建一个UserService,充当Bean,然后只有一个方法queryUserInfo。直接整个Test类,看测试结果即可。

public class ApiTest {

    @Test
    public void test_BeanFactory(){
        // 1.初始化 BeanFactory
        DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();

        // 2.注册bean
        BeanDefinition beanDefinition = new BeanDefinition(UserService.class);
        beanFactory.registerBeanDefinition("userService", beanDefinition);

        // 3.获取bean
        UserService userService = (UserService) beanFactory.getBean("userService");
        userService.queryUserInfo();
    }

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

我叫小八

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值