上一章节的Bean定义以及注册获取实现的简单,只有一个类就完成了这些功能,但是不容易扩展以及安全性的问题,这一章节就需要考虑涉及类之间的关联,就会复杂一些。
上一章节是自己创建了实例Bean传给了容器,这一章节就需要模拟Spring的方式容器创建Bean而不是在调用的时候传递一个实例化好的Bean对象,然后这次也要考虑单例,一个对象全局只有一个,在对象第二次获取的时候就可以从存储的地方取出来。
Bean注册时候只注册类的信息而不会把实例化信息注册到Spring 容器中,就需要更改BeanDefinition里的属性Object为Class,具体的其他类我们后面一一介绍。
1.工程实现
test单元测试文件工程
2.UML类图
这个类图我有点骄傲,哈哈
先根据类图介绍一下每个类大致都是干嘛的有个印象否则懵懵的
1.Bean工厂
按Bean工厂来说有4个类都是以BeanFactory为结尾的,先说下BeanFactory。
BeanFactory:接口类,只用来提供获取bean对象的方法
AbstractBeanFactory:抽象类,这个类主要是实现BeanFactory接口的getBean方法,此时这个类用了模板模式,先获取单例对象方(getSingleton()),获取不到再获取Bean定义方法(getBeanDefinition())以后在创建bean(createBean())对象操作
AbstractAutowireCapableBeanFactory:抽象类,继承AbstractBeanFactory,主要实现实例化bean的过程createBean方法。
DefaultListableBeanFactory:普通类,继承AbstractAutowireCapableBeanFactory,主要是获取Bean定义对象将父类方法实现操作(getBeanDefinition()),并实现了注册bean的操作(需要实现其他接口后续在讲)。
2.Bean定义BeanDefinition
BeanDefinition:普通类,用来定义bean的类对象,被DefaultListableBeanFactory类依赖,因为此类要注册与获取BeanDefinition啊。
BeanDefinitionRegistry:接口类,用来定义bean注册方法(registerBeanDefinition()),被DefaultListableBeanFactory类实现,就是上面说的注册Bean定义。
3.Bean单例
SingletonBeanRegistry:接口类,定义了获取单例对象的接口(getSingleton()),要习惯这种方式就是接口定义获取,但不定义添加,这个就是安全的体现,实现这个接口就可以达到只获取不能随意调用添加的操作。
DefaultSingletonBeanRegistry:普通类,实现SingletonBeanRegistry类的getSingleton()实现方式获取单例类对象,又添加了单例Bean的添加方法(addSingleton()),AbstractBeanFactory继承此类在创建Bean对象时进行单例Bean对象的添加。
这样梳理下来是不是一目了然,不同的类有不同的职责,每个类把自己的职责划分好做好,其他类通过不同的设计协调搭配,使整个类共同运作达到功能实现。
3.代码实现
1.BeanDefinition:
BeanDefinition:将beanClass改为了Class类,这样bean对象就可以是类信息了
// Bean定义
public class BeanDefinition {
// 按上一章的话这里已经把Object改成了Class,这样就可以把bean的实例化操作放到容器中处理了
private Class beanClass;
public BeanDefinition(Class beanClass) {
this.beanClass = beanClass;
}
public Class getBeanClass() {
return beanClass;
}
public void setBeanClass(Class beanClass) {
this.beanClass = beanClass;
}
}
2.单例类接口和实现
SingletonBeanRegistry:这里定义了单例Bean的获取,为什么没有设计单例Bean的添加,原因在以下代码的注释里
// 单例注册接口
public interface SingletonBeanRegistry {
// 定义了获取单例对象的接口
Object getSingleton(String beanName);
/* I think by myself:此注册接口为什么只提供了getSingleton(),而没有提供addSingleton()
所有实现此接口的都具有了获取单例对象的权利,但是没有保存单例对象的权利
也就可以保证安全,而不是任意的子实现类都可以去保存添加单例对象,这样可以
指定想要的实现类自己去添加保存实例,如:DefaultSingletonBeanRegistry实现类
*/
}
DefaultSingletonBeanRegistry:将接口的功能实现,将bean对象存储到Map里,获取时从map里获取,这里为什么addSingleton()方法是采用protected根据java修饰符来说这个是受保护的方法,不能够被其他类随意调用,比如new 之类的实例化,但是如果继承就可以调用此方法,单例数据的添加本来就应该是很隐秘的,所以也不能任意写在SingletonBeanRegistry接口类里,原因是如果写在此类里任意类实现都必须实现添加单例类,对设计来说也不合理,对单例来说也不安全
// 单例类注册实现方法
public class DefaultSingletonBeanRegistry implements SingletonBeanRegistry {
private Map<String, Object> singletonObjects = new HashMap<String, Object>();
// 在此方法中主要实现了获取单例对象方法
@Override
public Object getSingleton(String beanName) {
return singletonObjects.get(beanName);
}
// 实现了受保护的addSingleton方法,这个方法可以被继承此类的其他类调用
protected void addSingleton(String beanName, Object singletonObject) {
singletonObjects.put(beanName, singletonObject);
}
// protected修饰符的好处是如果new 此类是不能调用addSingleton,只有继承此类才可以
}
3.以BeanFactory为结尾的类
BeanFactory:定义了获取Bean对象的方法
// 定义bean工厂接口
public interface BeanFactory {
// 获取bean
Object getBean(String name) throws BeansException;
}
AbstractBeanFactory:此类设计很巧妙用了模板设计模式,getBean()获取了Bean对象,但是如果Bean没有被注册呢那么就需要创建Bean,但是此类单一原则是获取Bean对象,创建Bean对象,Bean定义的获取则需要不同的类的展示,这时创建了抽象类也是受保护的类,目的在于继承此类时去实现getBeanDefinition()与createBean();
public abstract class AbstractBeanFactory extends DefaultSingletonBeanRegistry implements BeanFactory {
/*
抽象类的getBean方法定义了模板方法,先获取单例bean,如没获取到则取出bean定义做相应的实例化操作,
最后创建bean,此方法是调用过程,而getBeanDefinition(获取bean定义)方法与createBean(创建bean)方法
则是由不同的实现方法实现功能
*/
@Override
public Object getBean(String name) throws BeansException {
// 从单例对象获取bean
Object bean = getSingleton(name);
if (bean != null) {
System.out.println("因为存在对象,从单例容器中取出对象");
return bean;
}
// 获取Bean定义类
BeanDefinition beanDefinition = getBeanDefinition(name);
// 创建Bean
return createBean(name, beanDefinition);
}
protected abstract BeanDefinition getBeanDefinition(String beanName) throws BeansException;
protected abstract Object createBean(String beanName, BeanDefinition beanDefinition) throws BeansException;
}
AbstractAutowireCapableBeanFactory:AbstractBeanFactory类的createBean()实现,创建Bean对象并添加到单例对象里,并返回Bean对象
// 真正实例化Bean类,也就是说真正的获取类实例对象了
public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory {
@Override
protected Object createBean(String beanName, BeanDefinition beanDefinition) throws BeansException {
Object bean = null;
try {
// 获得beanDefinition里beanClass的字段的新实例
bean = beanDefinition.getBeanClass().newInstance();
} catch (InstantiationException | IllegalAccessException e) {
throw new BeansException("Instantiation of bean failed", e);
}
// 获取bean实例以后添加到单例对象中
addSingleton(beanName, bean);
return bean;
}
}
DefaultListableBeanFactory:继承了AbstractAutowireCapableBeanFactory类和实现了BeanDefinitionRegistry 就有了Bean定义的注册和获取。
/*
DefaultListableBeanFactory 在 Spring 源码中也是一个非常核心的类,在我们目前的实现中也是逐步贴近于源码,与源码类名保持一致。
*/
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;
}
/*
1.DefaultListableBeanFactory继承了AbstractAutowireCapableBeanFactory类,也就具备了接口BeanFactory和AbstractBeanFactory
中的一连串的功能实现。所有有时候你会看到的一些类的强转,调用某些方法,也是因为你强转的类实现接口或继承了某些类。
2.除此之外这个类还实现了接口BeanDefinitionRegistry中的registerBeanDefinition方法,当然你还能看到一个getBeanDefinition的实现
这个方法我们提到过,它是抽象类AbstractBeanFactory中定义的抽象方法。现在注册bean的定义和获取bean定义就可以同时使用了,是不是感觉这个套路蛮深的
接口定义了注册,抽象类定义了获取,都集中在DefaultListableBeanFactory中的beanDefinationMap里。
*/
}
其他依赖的类,Bean异常处理类
public class BeansException extends RuntimeException {
public BeansException(String msg) {
super(msg);
}
public BeansException(String msg, Throwable cause) {
super(msg, cause);
}
}
这个篇章简单的Bean容器就搭建完成了。
咱们来测试
4.测试
测试前准备
public class UserService {
public void queryUserInfo(){
System.out.println("查询用户信息");
}
}
单元测试类:单元测试中除了包括;Bean 工厂、注册 Bean、获取 Bean,三个步骤,还额外增加了一次对象的获取和调用。这里主要测试验证单例对象的是否正确的存放到了缓存中。
public class ApiTest03 {
// 第三章测试
@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();
}
}
验证成功!
分享,码字不易,点赞,关注再走被