IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> Spring手撸03: 使用设计模式 实现Bean的定义/注册/获取 -> 正文阅读

[Java知识库]Spring手撸03: 使用设计模式 实现Bean的定义/注册/获取

撸了一遍明白为什么用封装一个ApplicationContext了, 里面很多的方法继承下来, 要去调用都一脸懵逼.

所以哦豁,又顿悟了一下为什么很多抽象类的那些实现好的方法要包保护了, 只给自己的子类去用, 外部是直接调用不到的.

就需要ApplicationContext去封装,把这些实现的方法开放出去.

先看一下整个流程之间类的关系, 这个也叫 类图

在这里插入图片描述

补充一下这些符号的说明

  • List item

  • -: private

  • +: public

  • ~: default

  • #: protected

  • 下划线: static

  • 斜体: 抽象类或方法(两个<<尖括号包起来也算)

冒号前有括号是方法名,反之变量名,冒号后是返回值,没有返回值可以直接连冒号一起省略

然后把这些类先创建好,简单归个类

在这里插入图片描述
然后上代码

BeanFactory

第一步还是BeanFactory,还是先这么简单

public interface BeanFactory {
    Object getBean(String name);
}

BeansException

专门抛Bean工厂中一些异常信息

public class BeansException extends NestedRuntimeException {

    public BeansException(String msg) {
        super(msg);
    }
}

BeanDefinition

然后上一篇我们讲过的, 是通过BeanDefinition只用来存储Bean的信息

@Data
public class BeanDefinition {

    private Class beanClass;

    //这里升级为只传类型,而不是实例 在需要的时候自己去实例
    public BeanDefinition(Class beanClass){
        this.beanClass=beanClass;
    }
}

单例注册接口定义SingletonBeanRegistry

因为上面只是传入了一个class, 所以需要一个能获取实例化对象的方法,开一个接口,让其他人去做实现

public interface SingletonBeanRegistry {

    Object getSingleton(String beanName);
}

单例注册实现DefaultSingletonBeanRegistry

这里就有了一个单例Bean的管理员

这是注册类,补充了一个注册Bean的方法.

public class DefaultSingletonBeanRegistry implements SingletonBeanRegistry {

    private final Map<String,Object> singletonObjects =new HashMap<>();

    /**
     * 实现获取单例的方法
     * @param beanName
     * @return
     */
    @Override
    public Object getSingleton(String beanName) {
        return singletonObjects.get(beanName);
    }

    /**
     * 提供一个包保护的方法 可以被继承此类的其他类调用
     * @param beanName
     * @param singletonObject
     */
    protected void addSingletonBean(String beanName,Object singletonObject){
        singletonObjects.put(beanName, singletonObject);
    }
}

抽象类定义(模板方法)AbstractBeanFactory

有了个获取类的方法,就可以getBean了?

public abstract class AbstractBeanFactory extends DefaultSingletonBeanRegistry implements BeanFactory {

    @Override
    public Object getBean(String beanName){
        //继承自DefaultSingletonBeanRegistry 的方法
        Object bean = getSingleton(beanName);
        if (bean != null){
            return bean;
        }
        //获取不到就两个抽象方法 让实现此类的去做实现
        BeanDefinition beanDefinition = getBeanDefinition(beanName);
        return createBean(beanName,beanDefinition);

    }

    protected abstract BeanDefinition getBeanDefinition(String name) throws BeansException;

    protected abstract Object createBean(String beanName,BeanDefinition bean) throws BeansException;
}

显然还不够,因为前面说了实例化的操作还没整好呢! 所以获取不到类的时候我们就要去实例化类.

但是我不管实现,我只负责获取Bean, 我们分工明确, 我需求提在这里,其他人去帮我实现吧!

这就是模板模式, 我不止定需求,我甚至把这些需求怎么串联起来都定成了一个模板

将核心的调用逻辑在这里定义好, 后续的人不用关心怎么我的方法要怎么去串联, 尽管实现自己的功能就好.

实例化Bean类 AbstractAutowireCapableBeanFactory

这个方法负责创建Bean,另外一个BeanDefinition的事情我就不管了,所以这是一个抽象类,只实现一个抽象方法,上面遗留的另外一个需求,让子类再去实现增强.

public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory{

    @Override
    protected Object createBean(String name, BeanDefinition beanDefinition) throws BeansException {
        Object bean;
        try {
            bean = beanDefinition.getBeanClass().newInstance();
        }catch (InstantiationException | IllegalAccessException e) {
            throw new BeansException("In");
        }
        addSingletonBean(name,bean);
        return bean;
    }
}

前面有Bean的管理类了,但是还没有BeanDefinition的管理类

核心实现类 DefaultListableBeanFactory

然后居然是让这个叫BeanFactory的去管理,我不能理解并且大为震惊.

public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory implements BeanDefinitionRegistry{

    private final Map<String,BeanDefinition> beanDefinitionMap =new HashMap<>();

    @Override
    public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition){
        beanDefinitionMap.put(beanName,beanDefinition);
    }

    @Override
    protected BeanDefinition getBeanDefinition(String name) throws BeansException {
        BeanDefinition beanDefinition = beanDefinitionMap.get(name);
        if (beanDefinition ==null) throw new BeansException("No bean named '"+name+"' is defined") ;
        return beanDefinition;
    }
}

不过现在都已经好了,包括Bean的定义 注册 获取,上测试代码

@Test
public void testBeanFactory(){
    //初始化 beanFactory
    DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
    //创建 bean信息
    BeanDefinition beanDefinition = new BeanDefinition(UserService.class);
    String beanName = "userService";
    //注册到工厂中
    beanFactory.registerBeanDefinition(beanName,beanDefinition);
    //获取实例
    UserService userService = (UserService) beanFactory.getBean(beanName);
    userService.queryUserInfo();
    //第二次再获取应该走单例
    UserService singletonUserService = (UserService)beanFactory.getBean(beanName);

    singletonUserService.queryUserInfo();
    //是否为单例
    System.out.println(userService);
    System.out.println(singletonUserService);
}
  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2022-04-26 11:28:38  更:2022-04-26 11:30:59 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 2:38:52-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码