0、上集回顾
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仓库