文章目录
前言
基于上一章节手写spring第一章-基础容器搭建
,我们制作了一个简单的spring容器完成bean的注入,但在功能和架构设计上,我们还有很多的不足。
需求分析
对于框架设计上,我们认为架构上必须保证在可预见的软件周期以内,项目是可以非常方便的扩展的,例如:对于现场的需求场景下,我们的框架只需要完成对加了注解的bean进行管理,我们想当然只需要写一个AutowireCapableBeanFactory
即可,但是未来某一天我们有需要处理配置bean,处理网络传输的bean等等,我们是不是又得重新写一个容器,然后复制粘贴一些与AutowireCapableBeanFactory
相同的代码段呢?
很显然,出现这种情况,就是架构设计上的不足,这样的做法,会导致大量冗余的代码出现。
接下来还有第二个问题,在上一章节,我们BeanDefinition
存储bean
的时候,存储的都是实例化的对象,这很显然是非常浪费内存内存的行为,所以在本章节我们也需要对此问题进行优化。
设计
思路分析
针对第一个问题,bean需要保证方便扩展,复用通用逻辑,我们可以进行如下设计,既然我们后续可能会出现各式各样的bean容器,那么我们就设计一个接口,将其命名为BeanFactory
,这个类也只有一个方法即getBean()
用这个接口来约束后续bean容器类的行为。
有了这么一个行为,考虑到后续容器可能会取单例对象,也可能会取多例对象,且获取单例对象的方式基本都是一样的,那么我们就可以设计一个单例对象容器类,所以我们就可以使用模板方法设计设计一个抽象的容器类AbstractBeanFactory
继承BeanFactory
实现getBean()
,为了保证通用性,我们需要抽取共性逻辑,即先通过单例对象容器获取单例对象,若单例对象容器中不存在,则去BeanDefinition
容器中获取对应的BeanDefinition
,再创建一个bean对象,但是我们对不同容器获取BeanDefinition的方式以及创建bean的方式都不确定,怎么办呢?那么我们就将这两个动作设计成抽象类,由后续继承该类的容器类自行实现。
上面已经说了,获取单例bean的方式基本都是一样的,但考虑扩展性以及单一职责原则,我们可以设计一个单例对象注册接口BeanDefinitionRegistry
约束一下所有单例对象管理器的所需行为,然后编写一个DefaultSingletonBeanRegistry
实现一个获取单例对象、注册单例对象的两个方法。
接下来我们就需要分析一下基于注解的bean容器的设计了,考虑到注解的多样性,我们getBeanDefinition
的方式可能会不同,所以我们还得再抽象一层,编写一个AbstractAutowireCapableBeanFactory
,实现createBean
,将getBeanDefinition
留予后续继承者实现。
说了这么多,我们忘记了一个重要的问题,BeanDefinition
要从哪来呢?我们在上面地方存储BeanDefinition呢?所以我们还需设计一个存储BeanDefinition
的接口,BeanDefinitionRegistry
交给具体实现bean容器的类完成该行为。
类图
代码结构
代码
BeanFactory
package cn.shark.springframework.beans.factory;
import cn.shark.springframework.beans.BeansException;
/**
* 将bean工厂设置为接口,便于后续进行各式各样的扩展
*/
public interface BeanFactory {
Object getBean(String name) throws BeansException;
}
AbstractBeanFactory
package cn.shark.springframework.beans.factory.support;
import cn.shark.springframework.beans.BeansException;
import cn.shark.springframework.beans.factory.BeanFactory;
import cn.shark.springframework.beans.factory.config.BeanDefinition;
public abstract class AbstractBeanFactory extends DefaultSingletonBeanRegistry implements BeanFactory {
/**
* 使用模板方法模式保证后面的bean容器只需专注自己的责任,以及统一bean容器规范
* @param name
* @return
* @throws BeansException
*/
public Object getBean(String name) throws BeansException {
Object singleton = getSingleton(name);
if (singleton!=null){
return singleton;
}
BeanDefinition beanDefinition = getBeanDefinition(name);
return createBean(name,beanDefinition);
}
protected abstract BeanDefinition getBeanDefinition(String beanName) throws BeansException;
/**
* 创建bean,并且放到单例容器中
* @param beanName
* @param beanDefinition
* @return
* @throws BeansException
*/
protected abstract Object createBean(String beanName, BeanDefinition beanDefinition)throws BeansException;
}
SingletonBeanRegistry
package cn.shark.springframework.beans.factory.config;
/**
* 单例注册表
*/
public interface SingletonBeanRegistry {
Object getSingleton(String beanName);
}
DefaultSingletonBeanRegistry
package cn.shark.springframework.beans.factory.support;
import cn.shark.springframework.beans.factory.config.SingletonBeanRegistry;
import java.util.HashMap;
import java.util.Map;
public class DefaultSingletonBeanRegistry implements SingletonBeanRegistry {
private Map<String, Object> singletonObjects = new HashMap<String, Object>();
public Object getSingleton(String beanName) {
return singletonObjects.get(beanName);
}
protected void addSingleton(String beanName, Object singletonObject) {
singletonObjects.put(beanName, singletonObject);
}
}
AbstractAutowireCapableBeanFactory
package cn.shark.springframework.beans.factory.support;
import cn.shark.springframework.beans.BeansException;
import cn.shark.springframework.beans.factory.config.BeanDefinition;
public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory {
protected Object createBean(String beanName, BeanDefinition beanDefinition) throws BeansException {
Object bean = null;
try {
bean = getBeanDefinition(beanName).getBeanClass().newInstance();
} catch (InstantiationException e) {
throw new BeansException("Instantiation of bean failed", e);
} catch (IllegalAccessException e) {
throw new BeansException("Instantiation of bean failed", e);
}
return bean;
}
}
DefaultListableBeanFactory
package cn.shark.springframework.beans.factory.support;
import cn.shark.springframework.beans.BeansException;
import cn.shark.springframework.beans.factory.config.BeanDefinition;
import java.util.HashMap;
import java.util.Map;
public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory implements BeanDefinitionRegistry {
private Map<String, BeanDefinition> beanDefinitionMap = new HashMap<>();
@Override
protected BeanDefinition getBeanDefinition(String beanName) throws BeansException {
BeanDefinition beanDefinition = beanDefinitionMap.get(beanName);
if (beanDefinition==null){
throw new BeansException("No bean named '" + beanName + "' is defined");
}
return beanDefinition;
}
@Override
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) {
beanDefinitionMap.put(beanName, beanDefinition);
}
}
BeanDefinitionRegistry
package cn.shark.springframework.beans.factory.support;
import cn.shark.springframework.beans.factory.config.BeanDefinition;
public interface BeanDefinitionRegistry {
void registerBeanDefinition(String beanName, BeanDefinition beanDefinition);
}