Spring手撸源码系列-实现bean定义、注册、获取、单例bean

上一章节的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();
    }
}

验证成功!

 分享,码字不易,点赞,关注再走被

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值