作者:小傅哥 博客:https://bugstack.cn
❝沉淀、分享、成长,让自己和他人都能有所收获!? ❞
你是否能提前预见复杂内容的设计问题?
讲道理,无论产品功能是否复杂,都有很大一部分程序员会写出一堆 if...else 来完成开发并顺利
上线。这主要是原因没法预见当前的需求,发展是否长远、流量是否庞大、迭代是否迅速,所以在被催促上线的情况,不写 if...else 是不可能的!
那你说,既然 if...else 实现的这么快,还考虑数据结构、算法逻辑、设计模式、系统架构吗?当然这基本要看你的项目在可预见下能活多久,如果一个项目至少存活一年,并且在这一年中又会不断的的迭代。就像;你做了一个营销优惠券系统,在各种条件下发放各种类型的券,如果在最开始没有考虑好系统设计和架构模式,那么当活动频发
、流量暴增
、需求迭代
下、最后你可能会挂在系统事故上!
我们在把系统设计的视角聚焦到具体代码实现上,你会有什么手段来实现你想要的设计模式呢?其实编码方式主要依托于:接口定义、类实现接口、抽象类实现接口、继承类、继承抽象类,而这些操作方式可以很好的隔离开每个类的基础功能、通用功能和业务功能,当类的职责清晰后,你的整个设计也会变得容易扩展和迭代。
接下来在本章节继续完善 Spring Bean 容器框架的功能开发,在这个开发过程中会用到较多的接口、类、抽象类,它们之间会有类的实现、类的继承。可以仔细参考这部分内容的开发实现,虽然并不会很复杂,但这种设计思路是完全可以复用到我们自己的业务系统开发中的。
在上一章节 《小试牛刀,实现一个简单的Bean容器》 我们初步依照 Spring Bean 容器的概念,实现了一个粗糙版本的代码实现。那么本章节我们需要结合已实现的 Spring Bean 容器进行功能完善,实现 Bean 容器关于 Bean 对象的注册和获取。
这一次我们把 Bean 的创建交给容器,而不是我们在调用时候传递一个实例化好的 Bean 对象,另外还需要考虑单例对象,在对象的二次获取时是可以从内存中获取对象的。此外不仅要实现功能还需要完善基础容器框架的类结构体,否则将来就很难扩容进去其他的功能了。
鉴于本章节的案例目标,我们需要将 Spring Bean 容器完善起来,首先非常重要的一点是在 Bean 注册的时候只注册一个类信息,而不会直接把实例化信息注册到 Spring 容器中。那么就需要修改 BeanDefinition 中的属性 Object 为 Class,接下来在需要做的就是在获取 Bean 对象时需要处理 Bean 对象的实例化操作以及判断当前单例对象在容器中是否已经缓存起来了。整体设计如图 3-1
getBean(String name)
,之后这个 Bean 工厂接口由抽象类 AbstractBeanFactory 实现。这样使用模板模式的设计方式,可以统一收口通用核心方法的调用逻辑和标准定义,也就很好的控制了后续的实现者不用关心调用逻辑,按照统一方式执行。那么类的继承者只需要关心具体方法的逻辑实现即可。small-spring-step-02
└── src
├── main
│ └── java
│ └── cn.bugstack.springframework.beans
│ ├── factory
│ │ ├── factory
│ │ │ ├── BeanDefinition.java
│ │ │ └── SingletonBeanRegistry.java
│ │ ├── support
│ │ │ ├── AbstractAutowireCapableBeanFactory.java
│ │ │ ├── AbstractBeanFactory.java
│ │ │ ├── BeanDefinitionRegistry.java
│ │ │ ├── DefaultListableBeanFactory.java
│ │ │ └── DefaultSingletonBeanRegistry.java
│ │ └── BeanFactory.java
│ └── BeansException.java
└── test
└── java
└── cn.bugstack.springframework.test
├── bean
│ └── UserService.java
└── ApiTest.java
工程源码:公众号「bugstack虫洞栈」,回复:Spring 专栏,获取源码
Spring Bean 容器类关系,如图 3-2
图 3-2
虽然这一章节关于 Spring Bean 容器的功能实现与 Spring 源码
中还有不少的差距,但以目前实现结果的类关系图来看,其实已经具备了一定的设计复杂性,这些复杂的类关系设计在各个接口定义和实现以及在抽象类继承中都有所体现,例如:
综上这一部分的类关系和实现过程还是会有一些复杂的,因为所有的实现都以职责划分、共性分离以及调用关系定义为标准搭建的类关系。这部分内容的学习,可能会丰富你在复杂业务系统开发中的设计思路。
cn.bugstack.springframework.beans.factory.config.BeanDefinition
public class BeanDefinition {
private Class beanClass;
public BeanDefinition(Class beanClass) {
this.beanClass = beanClass;
}
// ...get/set
}
cn.bugstack.springframework.beans.factory.config.SingletonBeanRegistry
public interface SingletonBeanRegistry {
Object getSingleton(String beanName);
}
cn.bugstack.springframework.beans.factory.config.DefaultSingletonBeanRegistry
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);
}
}
cn.bugstack.springframework.beans.factory.support.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;
}
cn.bugstack.springframework.beans.factory.support.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;
}
}
newInstance
,其实这块会埋下一个坑,有构造函数入参的对象怎么处理?可以提前思考addSingleton
方法存放到单例对象的缓存中去。cn.bugstack.springframework.beans.factory.support.DefaultSingletonBeanRegistry
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;
}
}
cn.bugstack.springframework.test.bean.UserService
public class UserService {
public void queryUserInfo(){
System.out.println("查询用户信息");
}
}
cn.bugstack.springframework.test.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();
}
查询用户信息
查询用户信息
Process finished with exit code 0
- END -