手写模拟一个简单的Spring(中)

0、上集回顾

手写模拟一个简单的Spring(上)

3、手写基础功能-- Spring的bean创建

3.1、待注册的类存储

我们已经通过自定义注解拿到需要注册的类,扫描一次全路径的代价太大了,而且步骤也繁多,这里选择用一个 Map 将扫描到的类全部缓存起来。

这里就引出一个Spring中比较重要的点 BeanDefinition

什么是 BeanDefinition? 详细解读传送门

在Spring框架中,BeanDefinition是描述和定义Spring容器中的Bean的元数据对象。它包含了定义Bean的相关信息,例如Bean的类名、作用域、生命周期等。

BeanDefinition对象通常由Spring容器在启动过程中根据配置信息或注解生成。是Sping Ioc容器管理的核心数据结构之一,用于保存Bean的配置和属性。

public class BeanDefinition {

    private Class type;
    private String scope;
    private boolean isLays;

    public Class getType() {
        return type;
    }

    public void setType(Class type) {
        this.type = type;
    }

    public String getScope() {
        return scope;
    }

    public void setScope(String scope) {
        this.scope = scope;
    }

    public boolean isLays() {
        return isLays;
    }

    public void setLays(boolean lays) {
        isLays = lays;
    }
}

简单定义下属性,后面有需要我们再添加。有了BeanDefinition后就可以存储bean的元信息了,在容器中按对应的beanName存储上BeanDefinition。

请添加图片描述

3.2、Bean的创建与获取

有了bean定义后,我们就可以来实例化bean了。

public Object getBean(String beanName) {
        if (!beanDefinitionMap.containsKey(beanName)){
            throw new NullPointerException("不存在的BeanDefinition");
        }
        BeanDefinition definition = beanDefinitionMap.get(beanName);
        Object bean = doCreateBean(beanName, definition);

        return bean;
    }

    public Object doCreateBean(String beanName, BeanDefinition definition) {
        Class aClass = definition.getType();

        try {
            return aClass.getConstructor().newInstance();
        } catch (InstantiationException e) {
            throw new RuntimeException(e);
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        } catch (InvocationTargetException e) {
            throw new RuntimeException(e);
        } catch (NoSuchMethodException e) {
            throw new RuntimeException(e);
        }
    }

这里再运行之前的测试方法,我这里还加两句,也补充了一个不存在bean获取。
在这里插入图片描述

3.3、单例bean与多例bean

看到这里可能有小伙伴会有疑问了:为啥模拟的Spring默认是多例bean呢,Spring默认的可是单例bean?

哈哈,收到,马上改造它。

先定义一个注解,用来表示是单例还是原型

/**
 * @author yearOfTheRain
 * @date 2024/7/2 21:08
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Scope {

    String value();
}

扫描的时候直接将对应的Scope信息存储
请添加图片描述

既然是单例bean,那就意味着这个bean只创建了一次,其他地方都是拿同一个对象使用的,这里我们用一个Map来缓存单例bean,Spring中也有对应的设计,叫做单例池。

在这里插入图片描述
获取bean的方法也进行下简单改造,单例bean直接从单例池中获取
在这里插入图片描述
再运行下测试类,这里可以看到单例和多例的效果都有了

请添加图片描述

请添加图片描述

4、手写中阶功能-- 依赖注入

这里是下集预告,就这两天马上出下集,敬请各位期待。整体代码完成后源码会上传gitee仓库

  • 18
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值