文章目录
一、目标
在上一节中我们实现了一个简单的Bean容器,这次我们需要结合已经实现的Spring Bean容器进行功能完善,实现Bean容器关于Bean对象的注册和获取。
这次我们把Bean的创建交给容器,而不是像之前在调用的时候传递一个实例化好的Bean对象,另外还需要考虑单例对象,在对象的二次获取时是可以从内存中获取对象的。此外不仅要实现功能,还需要完善基础容器框架的类结构体,否则后面很难进行扩容其它的功能。
二、设计
根据这次的目标,我们需要将Spring Bean容器完善起来。首先非常重要的一点是在Bean注册的时候只注册一个类信息,而不是把实例化信息注册到容器中。那么就需要修改BeanDefinition中的属性Object为Class,接下来需要做的就是在获取Bean对象时需要处理Bean对象的实例化操作,以及判断当前单例对象在容器中是否已经缓存起来了。
- 首先需要定义BeanFactory这样一个Bean工厂,提供获取Bean的方法getBean,这个Bean工厂接口由抽象类AbstractBeanFactory实现。这里使用的是模板模式,可以统一接口通用核心方法的调用逻辑和标准定义,也很好的控制了后续的实现者不用关心调用逻辑,按照统一方式执行。那么类的继承者只需要关心具体方法的逻辑实现即可。
- 那么在继承抽象类AbstractBeanFactory后的AbstractAutowireCapableBeanFactory就可以实现相应的抽象方法了,因为AbstractAutowireCapableBeanFactory本身也是抽象类,所以它只会实现属于自己的抽象方法,其它的抽象方法由继承者AbstractAutowireCapableBeanFactory的类实现。这里就体现了类实现过程中的各司其职,每个类就关心属于自己的内容。
- 还有一个很重要的就是关于单例SingletonBeanRegistry的接口定义实现,而DefaultSingletonBeanRegistry对该接口实现后,会被抽象类AbstractBeanFactory继承。最后AbstractBeanFactory就是一个非常完整且强大的抽象类了,也很好的体现出它对模板模式的抽象定义。
三、实现
1、工程结构
Spring Bean容器类关系图,如下:
- BeanFactory的定义由AbstractBeanFactory抽象类实现接口的getBean方法
- 而AbstractBeanFactory又继承实现了SingletonBeanRegistry的DefaultSingletonBeanRegistry类,这样AbstractBeanFactory抽象类就具备了单例Bean的注册功能。
- AbstractBeanFactory中又定义了两个抽象方法:getBeanDefinition()和createBean(),这两个抽象方法分别由DefaultListableBeanFactory、AbstractAutowireCapableBeanFactory实现。
- 最终DefaultListableBeanFactory还会继承抽象类AbstractAutowireCapableBeanFactory,也就可以调用抽象类中的createBean()方法了。
2、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;
}
}
- 在Bean定义类中已经把上节的 Object bean 替换成Class,这样就可以把Bean的实例化操作放到容器中处理了。
3、单例注册接口和实现
public interface SingletonBeanRegistry {
/**
* 获取单例对象
*/
Object getSingleton(String name);
}
- 这个类主要定义了一个获取单例对象的接口
public class DefaultSingletonBeanRegistry implements SingletonBeanRegistry {
private Map<String, Object> singletonObjects = new HashMap<>();
@Override
public Object getSingleton(String name) {
return singletonObjects.get(name);
}
protected void addSingleton(String beanName, Object singletonObject) {
singletonObjects.put(beanName, singletonObject);
}
}
- 这个类只要实现了getSingleton方法,同时实现一个受保护的addSingleton方法,这个方法可以被继承此类的其它类调用,包括:AbstractBeanFactory以及继承的DefaultListableBeanFactory调用。
4、抽象类定义模板方法(AbstractBeanFactory)
public abstract class AbstractBeanFactory extends DefaultSingletonBeanRegistry implements BeanFactory {
@Override
public Object getBean(String name) throws BeansException {
Object bean = getSingleton(name);
if (bean != null) {
return bean;
}
BeanDefinition beanDefinition = getBeanDefinition(name);
return createBean(name, beanDefinition);
}
protected abstract BeanDefinition getBeanDefinition(String beanName) throws BeansException;
protected abstract Object createBean(String beanName, BeanDefinition beanDefinition) throws BeansException;
}
- AbstractBeanFactory首先继承了DefaultSingletonBeanRegistry,也就具备了使用单例注册类方法。
- 接下来就是对接口BeanFactory的实现,在getBean()方法的实现中,主要是对单例对象的获取以及在获取不到的情况下需要拿到bean的定义做相应bean实例化操作。在getBean()中并没有自身去实现这些方法,而是定义了调用过程以及提供了抽象方法,由实现此抽象类的其它类做相应的实现。
- 后续继承抽象类AbstractBeanFactory的类有两个,包括:AbstractAutowireCapableBeanFactory、DefaultListableBeanFactory,这两个类分别做了相应的实现处理。
5、实例化Bean类(AbstractAutowireCapableBeanFactory)
public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory {
@Override
protected Object createBean(String beanName, BeanDefinition beanDefinition) throws BeansException {
Object bean = null;
try {
bean = beanDefinition.getBeanClass().newInstance();
} catch (InstantiationException | IllegalAccessException e) {
throw new BeansException("Instantiation of bean failed", e);
}
addSingleton(beanName, bean);
return bean;
}
}
- 在AbstractAutowireCapableBeanFactory类中实现了Bean的实例化操作。
- 处理完Bean对象的实例化后,直接调用addSingleton方法存放到单例对象的缓存中去。
6、核心类实现(DefaultListableBeanFactory)
```java
public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory implements BeanDefinitionRegistry {
private Map<String, BeanDefinition> beanDefinitionMap = new HashMap<>();
@Override
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) {
beanDefinitionMap.put(beanName, beanDefinition);
}
@Override
public 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;
}
}
- DefaultListableBeanFactory继承了AbstractAutowireCapableBeanFactory类,也具备了接口BeanFactory和AbstractBeanFactory等一连串的功能实现。
- 这个类还实现了BeanDefinitionRegistry中的registerBeanDefinition()方法,当然还有一个getBeanDefinition的实现,这个方法就是前文提过它是抽象类AbstractBeanFactory中定义的抽象方法。现在注册Bea定义和获取Bean定义就可以同时使用了,接口定义了注册,抽象类定义了获取,都集中在DefaultListableBeanFactory中的beanDefinitionMap里。
四、测试
1、事先准备
public class UserService {
public void queryUserInfo() {
System.out.println("查询用户信息");
}
}
2、测试用例
public class ApiTest {
@Test
public void test() {
//初始化BeanFactory
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
//注册bean
BeanDefinition beanDefinition = new BeanDefinition(UserService.class);
beanFactory.registerBeanDefinition("userService", beanDefinition);
//第一次获取bean
UserService userService = (UserService) beanFactory.getBean("userService");
userService.queryUserInfo();
//第二次获取bean from singleton
UserService userService_singleton = (UserService) beanFactory.getBean("userService");
userService_singleton.queryUserInfo();
}
}
3、测试结果
- 这里两次测试信息,一次是获取Bean是直接创建的对象,第二次是从缓存中获取的实例化对象。