手写Spring框架-BeanDefinition and BeanDefinitionRegisty
建议订阅博主专栏,从下到上系统手写spring源码,体会其中过程!
- 定义BeanDefinition对象,由于我们做的是简易的spring框架,只需要记录bean的Class信息,代码如下:
/**
* BeanDefinition实例保存bean的信息,包括class类型、方法构造参数、是否为单例等,此处简化只包含class类型
* @author WangChao
* @version 1.0
* @date 2023/6/14 12:07
*/
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;
}
}
- 定义单例注册表接口,用于和DefaultSingletonBeanRegistry分离开,定义获取单例bean的方法,spring默认采用的单例模式注册bean对象
/**
* 单例注册表
* @author WangChao
* @version 1.0
* @date 2023/6/14 12:09
*/
public interface SingletonBeanRegistry {
Object getSingleton(String beanName);
}
- 编写单例bean注册实现类,用一个HashMap记录beanName和Object对象注册关系,为后边的AbstractBeanFactory中getBean服务
/**
* 单例bean注册实现类
* @author WangChao
* @version 1.0
* @date 2023/6/14 12:15
*/
public class DefaultSingletonBeanRegistry implements SingletonBeanRegistry {
private Map<String, Object> singletonObjects = new HashMap<>();
@Override
public Object getSingleton(String beanName) {
return singletonObjects.get(beanName);
}
protected void addSingleton(String beanName,Object singletonObject){
singletonObjects.put(beanName,singletonObject);
}
}
- 编写AbstractBeanFactory,这是一个顶层抽象方法,里面有获取bean的初步实现,如果在单例HashMap中能拿到对象,则获取该bean对象,然后返回,拿不到,则调用抽象方法createBean方法
/**
* 抽象创建bean的工厂
* @author WangChao
* @version 1.0
* @date 2023/6/14 12:13
*/
public abstract class AbstractBeanFactory extends DefaultSingletonBeanRegistry implements BeanFactory {
@Override
public Object getBean(String beanName) throws BeansException {
Object bean = getSingleton(beanName);
if(bean != null){
return bean;
}
BeanDefinition beanDefinition = getBeanDefinition(beanName);
return createBean(beanName,beanDefinition);
}
/**
* 创建一个bean
* @param beanName bean名称
* @param beanDefinition
* @return
* @throws BeansException
*/
protected abstract Object createBean(String beanName,BeanDefinition beanDefinition) throws BeansException;
/**
* 根据bean名称获取BeanDefinition
* @param beanName
* @return
* @throws BeansException
*/
protected abstract BeanDefinition getBeanDefinition(String beanName) throws BeansException;
}
其中实现的BeanFactory是一个获得bean的工厂,实现其接口,重载getBean方法
/**
* bean容器
* @author WangChao
* @version 1.0
* @date 2023/6/14 11:15
*/
public interface BeanFactory {
/**
* 获取bean
* @param beanName
* @return
*/
Object getBean(String beanName);
}
- 编写AbstractAutowireCapableBeanFactory类,这个类继承了上面写的AbstractBeanFactory,重写了里面的createBean方法,该方法调用了doCreateBean方法,在doCreateBean方法中根据beanName和在HashMap拿到的beanDefinition通过反射拿到Class对象,后new一个Class实例对象,再将该对象放到单例HashMap中,key是beanName,代码如下:
/**
* @author WangChao
* @version 1.0
* @date 2023/6/14 12:35
*/
public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory{
@Override
protected Object createBean(String beanName, BeanDefinition beanDefinition) throws BeansException{
return doCreateBean(beanName,beanDefinition);
}
/**
* 创建bean示例
* @param beanName
* @param beanDefinition
* @return
* @throws BeansException
*/
protected Object doCreateBean(String beanName,BeanDefinition beanDefinition) throws BeansException{
Class beanClass = beanDefinition.getBeanClass();
Object bean;
try{
bean = beanClass.newInstance();
} catch (Exception e) {
throw new BeansException("Instantiation of bean failed", e);
}
addSingleton(beanName,bean);
return bean;
}
- 编写DefaultListableBeanFactory,该类继承了AbstractBeanFactory、AbstractAutowireCapableBeanFactory,实现了BeanDefinitionRegistry拥有getBean、setBean、registerBeanDefinition、getBeanDefinition等方法同时 AbstractBeanFactory又继承了单例bean的get方法,可以获取单例bean,总的来说,这个类可以提供更多的方法,集成了以上说的类,并重写了getBeanDefinition、registerBeanDefinition这两个方法,也是用一个HashMap代码如下:
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);
}
}
该类拥有的方法如下图:
总结
通过手写该BeanDefinition的注册和获取过程,了解到了bean在容器中封装和获取,本质是HashMap和单例的应用,同时用到了经典的设计模式,使得代码更加的优雅,其中接口和集成的使用更是秒不可言,一层层实现了最终的目标!