手写spring第二章-运用设计模式编写可扩展的容器

前言

基于上一章节手写spring第一章-基础容器搭建
,我们制作了一个简单的spring容器完成bean的注入,但在功能和架构设计上,我们还有很多的不足。

需求分析

对于框架设计上,我们认为架构上必须保证在可预见的软件周期以内,项目是可以非常方便的扩展的,例如:对于现场的需求场景下,我们的框架只需要完成对加了注解的bean进行管理,我们想当然只需要写一个AutowireCapableBeanFactory即可,但是未来某一天我们有需要处理配置bean,处理网络传输的bean等等,我们是不是又得重新写一个容器,然后复制粘贴一些与AutowireCapableBeanFactory相同的代码段呢?
很显然,出现这种情况,就是架构设计上的不足,这样的做法,会导致大量冗余的代码出现。

接下来还有第二个问题,在上一章节,我们BeanDefinition存储bean的时候,存储的都是实例化的对象,这很显然是非常浪费内存内存的行为,所以在本章节我们也需要对此问题进行优化。

设计

思路分析

针对第一个问题,bean需要保证方便扩展,复用通用逻辑,我们可以进行如下设计,既然我们后续可能会出现各式各样的bean容器,那么我们就设计一个接口,将其命名为BeanFactory,这个类也只有一个方法即getBean()用这个接口来约束后续bean容器类的行为。

有了这么一个行为,考虑到后续容器可能会取单例对象,也可能会取多例对象,且获取单例对象的方式基本都是一样的,那么我们就可以设计一个单例对象容器类,所以我们就可以使用模板方法设计设计一个抽象的容器类AbstractBeanFactory继承BeanFactory实现getBean(),为了保证通用性,我们需要抽取共性逻辑,即先通过单例对象容器获取单例对象,若单例对象容器中不存在,则去BeanDefinition容器中获取对应的BeanDefinition,再创建一个bean对象,但是我们对不同容器获取BeanDefinition的方式以及创建bean的方式都不确定,怎么办呢?那么我们就将这两个动作设计成抽象类,由后续继承该类的容器类自行实现。

上面已经说了,获取单例bean的方式基本都是一样的,但考虑扩展性以及单一职责原则,我们可以设计一个单例对象注册接口BeanDefinitionRegistry约束一下所有单例对象管理器的所需行为,然后编写一个DefaultSingletonBeanRegistry实现一个获取单例对象、注册单例对象的两个方法。

接下来我们就需要分析一下基于注解的bean容器的设计了,考虑到注解的多样性,我们getBeanDefinition的方式可能会不同,所以我们还得再抽象一层,编写一个AbstractAutowireCapableBeanFactory,实现createBean,将getBeanDefinition留予后续继承者实现。

说了这么多,我们忘记了一个重要的问题,BeanDefinition要从哪来呢?我们在上面地方存储BeanDefinition呢?所以我们还需设计一个存储BeanDefinition的接口,BeanDefinitionRegistry交给具体实现bean容器的类完成该行为。

类图

在这里插入图片描述

代码结构

在这里插入图片描述

代码

BeanFactory

package cn.shark.springframework.beans.factory;

import cn.shark.springframework.beans.BeansException;

/**
 * 将bean工厂设置为接口,便于后续进行各式各样的扩展
 */
public interface BeanFactory {
    
    

    Object getBean(String name) throws BeansException;


}

AbstractBeanFactory

package cn.shark.springframework.beans.factory.support;


import cn.shark.springframework.beans.BeansException;
import cn.shark.springframework.beans.factory.BeanFactory;
import cn.shark.springframework.beans.factory.config.BeanDefinition;

public abstract class AbstractBeanFactory extends DefaultSingletonBeanRegistry implements BeanFactory {
    
    

    /**
     * 使用模板方法模式保证后面的bean容器只需专注自己的责任,以及统一bean容器规范
     * @param name
     * @return
     * @throws BeansException
     */
    public Object getBean(String name) throws BeansException {
    
    
        Object singleton = getSingleton(name);
        if (singleton!=null){
    
    
            return singleton;
        }
        BeanDefinition beanDefinition = getBeanDefinition(name);
        return createBean(name,beanDefinition);
    }

    protected abstract BeanDefinition getBeanDefinition(String beanName) throws BeansException;

    /**
     * 创建bean,并且放到单例容器中
     * @param beanName
     * @param beanDefinition
     * @return
     * @throws BeansException
     */
    protected abstract Object createBean(String beanName, BeanDefinition beanDefinition)throws BeansException;




}

SingletonBeanRegistry

package cn.shark.springframework.beans.factory.config;

/**
 * 单例注册表
 */
public interface SingletonBeanRegistry {
    
    

    Object getSingleton(String beanName);
}

DefaultSingletonBeanRegistry

package cn.shark.springframework.beans.factory.support;

import cn.shark.springframework.beans.factory.config.SingletonBeanRegistry;

import java.util.HashMap;
import java.util.Map;

public class DefaultSingletonBeanRegistry implements SingletonBeanRegistry {
    
    

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

    public Object getSingleton(String beanName) {
    
    
        return singletonObjects.get(beanName);
    }

    protected void addSingleton(String beanName, Object singletonObject) {
    
    
        singletonObjects.put(beanName, singletonObject);
    }
}

AbstractAutowireCapableBeanFactory

package cn.shark.springframework.beans.factory.support;

import cn.shark.springframework.beans.BeansException;
import cn.shark.springframework.beans.factory.config.BeanDefinition;

public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory {
    
    

    protected Object createBean(String beanName, BeanDefinition beanDefinition) throws BeansException {
    
    
        Object bean = null;

        try {
    
    
            bean = getBeanDefinition(beanName).getBeanClass().newInstance();
        } catch (InstantiationException e) {
    
    
            throw new BeansException("Instantiation of bean failed", e);
        } catch (IllegalAccessException e) {
    
    
            throw new BeansException("Instantiation of bean failed", e);
        }

        return bean;
    }
}

DefaultListableBeanFactory

package cn.shark.springframework.beans.factory.support;

import cn.shark.springframework.beans.BeansException;
import cn.shark.springframework.beans.factory.config.BeanDefinition;

import java.util.HashMap;
import java.util.Map;

public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory implements BeanDefinitionRegistry {
    
    

    private 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) {
    
    
        beanDefinitionMap.put(beanName, beanDefinition);
    }
}

BeanDefinitionRegistry

package cn.shark.springframework.beans.factory.support;

import cn.shark.springframework.beans.factory.config.BeanDefinition;

public interface BeanDefinitionRegistry {
    
    

    void registerBeanDefinition(String beanName, BeanDefinition beanDefinition);
}

测试

在这里插入图片描述

参考文献

第3章-初显身手-运用设计模式-实现-Bean-的定义-注册-获取.html

单一职责原则

UML基础(附绘制教程)

猜你喜欢

转载自blog.csdn.net/shark_chili3007/article/details/120073141