文章目录
- 前言
- 本章目标
- 一、实现
- 1、项目结构
- 2、BeanFactory-bean工厂
- 3、BeanDefinition -bean定义
- 4、单例注册接口定义和实现-SingletonBeanRegistry 、DefaultSingletonBeanRegistry
- 5、AbstractBeanFactory-抽象bean工厂类(定义模板方法)
- 6、AbstractAutowireCapableBeanFactory-实例化Bean
- 7、DefaultListableBeanFactory-bean工厂核心实现类
- 五、测试
- 1、准备的测试类
- 2、测试用例
- 3、测试结果
- 总结
前言
继续完善 Spring Bean 容器框架的功能开发
本章目标
1、bean的创建交给容器
2、getBean采用模板方法设计模式,指定调用过程和标准定义,控制了后续的实现者不用关心调用逻辑,按照统一方式执行
3、容器框架的类结构优化,方便后续功能的扩展
一、实现
1、项目结构
├─src
│ ├─main
│ │ ├─java
│ │ │ └─cn
│ │ │ └─ljc
│ │ │ └─springframework
│ │ │ └─beans
│ │ │ │ BeansException.java
│ │ │ │
│ │ │ └─factory
│ │ │ │ BeanFactory.java
│ │ │ │
│ │ │ ├─config
│ │ │ │ BeanDefinition.java
│ │ │ │ SingletonBeanRegistry.java
│ │ │ │
│ │ │ └─support
│ │ │ AbstractAutowireCapableBeanFactory.java
│ │ │ AbstractBeanFactory.java
│ │ │ BeanDefinitionRegistry.java
│ │ │ DefaultListableBeanFactory.java
│ │ │ DefaultSingletonBeanRegistry.java
│ │ │
│ │ └─resources
│ └─test
│ └─java
│ └─springframework
│ └─test
│ │ ApiTest.java
│ │
│ └─bean
│ UserService.java
2、BeanFactory-bean工厂
/**
* @desc Bean工厂
* @Author: ljc
* @Date: 2022/11/28 10:36
*/
public interface BeanFactory {
Object getBean(String name) throws BeansException;
}
上一章的BeanFactory 是一个类,这里把他抽象了,变成一个接口,方便扩展
3、BeanDefinition -bean定义
/**
* @desc Bean定义
* @Author: ljc
* @Date: 2022/11/28 10:35
*/
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;
}
}
上一章Object beanClass 改为Class beanClass,bean的实例化操作可以放到容器中去处理
4、单例注册接口定义和实现-SingletonBeanRegistry 、DefaultSingletonBeanRegistry
单例注册bean的接口
/**
* @desc 单例注册接口定义
* @Author: ljc
* @Date: 2022/11/30 17:27
*/
public interface SingletonBeanRegistry {
Object getSingleton(String beanName);
}
提供了一个获取单例bean的接口
单例注册bean的实现
/**
* @desc 单例注册接口的实现类
* @Author: ljc
* @Date: 2022/11/30 17:28
*/
public class DefaultSingletonBeanRegistry implements SingletonBeanRegistry {
/**
* @desc: 单例池
* @author: ljc
* @date: 2022/12/7 10:57
* @param:
* @return:
**/
private Map<String,Object> singletonObjects = new HashMap<>();
/**
* @desc: 获取单例bean
* @author: ljc
* @date: 2022/12/7 10:57
* @param: [beanName]
* @return: java.lang.Object
**/
@Override
public Object getSingleton(String beanName) {
return singletonObjects.get(beanName);
}
/**
* @desc: 入单例池
* @author: ljc
* @date: 2022/12/7 10:56
* @param: [beanName, singletonObject]
* @return: void
**/
protected void addSingleton(String beanName,Object singletonObject){
singletonObjects.put(beanName,singletonObject);
}
}
实现了获取单例bean的接口,并且定义了一个对象单例池,以及提供了添加对象到单例池的保护方法
保证单一职责,只负责处理单例Bean的处理
5、AbstractBeanFactory-抽象bean工厂类(定义模板方法)
/**
* @desc 抽象bean工厂类
* @Author: ljc
* @Date: 2022/12/7 11:10
*/
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;
}
新增了2个抽象方法,getBeanDefinition和createBean;
AbstractBeanFactory 继承于DefaultSingletonBeanRegistry,获得了单例注册bean的能力,并且实现了bean工厂的getBean方法
在getBean里面只定义了调用过程(模板模式),并没有自己去实现,让实现此抽象的类去完成。
PS:
这样使用模板模式 (opens new window)的设计方式,可以统一收口通用核心方法的调用逻辑和标准定义,也就很好的控制了后续的实现者不用关心调用逻辑,按照统一方式执行。那么类的继承者只需要关心具体方法的逻辑实现即可
6、AbstractAutowireCapableBeanFactory-实例化Bean
/**
* @desc 实例化Bean类
* @Author: ljc
* @Date: 2022/12/7 13:06
*/
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 本身也是一个抽象类
它只会实现属于自己的抽象方法,其他抽象方法由继承AbstractAutowireCapableBeanFactory 的类实现。
这里会有一个问题,如果是带参数的构造方法如何处理?(在源码里,其实是有一个寻找构造方法的判断处理)
7、DefaultListableBeanFactory-bean工厂核心实现类
/**
* @desc bena工厂核心实现类
* @Author: ljc
* @Date: 2022/12/7 13:33
*/
public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory implements BeanDefinitionRegistry{
// bean定义的缓存
private final 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) throws BeansException {
beanDefinitionMap.put(beanName, beanDefinition);
}
}
继承于AbstractAutowireCapableBeanFactory ,拥有了创建bean、获取bean的能力
并且实现了BeanDefinitionRegistry接口的,内部实现了egisterBeanDefinition(实现了Bean定义)
五、测试
1、准备的测试类
/**
* @desc 用户服务类
* @Author: ljc
* @Date: 2022/11/28 10:56
*/
public class UserService {
public void queryUserInfo(){
System.out.println("查询用户信息");
}
}
2、测试用例
/**
* @desc 测试
* @Author: ljc
* @Date: 2022/11/28 10:57
*/
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();
// 4.第二次获取 bean from Singleton
UserService userService_singleton = (UserService) beanFactory.getBean("userService");
userService_singleton.queryUserInfo();
System.out.println(userService);
System.out.println(userService_singleton);
}
}
测试案例主要包含了 初始化bean工厂、注册bean、获取bean。
上一章的测试用例,可以看到是通过new userService()来定义bean,现在是把UserService的class传给bean定义。
调用2次获取bean,主要是用于测试第二次获取时,是否从缓存里获取,按上述代码,结果是肯定的!
3、测试结果
查询用户信息
查询用户信息
springframework.test.bean.UserService@504bae78
springframework.test.bean.UserService@504bae78
Process finished with exit code 0
可以看到打印的对象是同一个
总结
可以看到本章节,增加了很多类和接口,为什么要设计成这样?
基于接口、抽象编程,便于扩展
松耦合,让每个类只承担自己职责的那部分,尽可能保证单一职责