手写一个mini版Spring:如何让容器能注册和获取单例 Bean
如今,我们每天都在面向 AI 工作,对着 AI 描述需求、审查代码、验收结果。效率确实提高了,但是我们的思考却越来越少了,好像也很少有同学再去研究一个框架,去认真看一段源码了。大部分人都会产生一个疑问,Claude、codex 这么厉害还有必要研究源码吗?还有必要懂底层吗?
其实,虽然 AI 的时代让“编码”贬值了,但让“工程能力”更值钱了。只有懂架构、懂设计、懂底层的人,才能理解复杂系统并拆解问题、才能读得懂 AI 写的代码、才能快速对 AI 纠错、才能让 AI 持续迭代。
所以,未来需要的不是会使用 AI 的人。未来真正稀缺的是能驾驭 AI,并对生成结果负责的人。
言归正传
要像spring一样向容器中注册和获取Bean,首先我们要定义几个核心的类并且知道它的流程。
我们的目的就是,把原来在代码里new对象 —> 对象由容器统一创建和管理
核心流程大概就是(如图)

核心类如下:
BeanDefinition(class):bean的定义,用来存放类对象
public class BeanDefinition {
private Class<?> beanClass;
public BeanDefinition(Class<?> beanClass) {
this.beanClass = beanClass;
}
public Class<?> getBeanClass() {
return beanClass;
}
public void setBeanClass(Class<?> beanClass) {
this.beanClass = beanClass;
}
}
BeanDefinitionRegistry(interface):注册bean定义、获取bean定义的接口
public interface BeanDefinitionRegistry {
/**
* 注册bean定义
* @param beanName bean的名称
* @param beanDefinition bean的定义
*/
void registerBeanDefinition(String beanName, BeanDefinition beanDefinition);
/**
* 获取bean定义
* @param beanName bean的名称
* @return BeanDefinition
*/
BeanDefinition getBeanDefinition(String beanName);
/**
* 判断是否存在bean定义
* @param beanName bean的名称
* @return boolean
*/
boolean containsBeanDefinition(String beanName);
}
BeanFactory(interface):获取单例bean的接口
public interface BeanFactory {
Object getBean(String beanName);
<T> T getBean(String beanName, Class<T> requiredType);
}
SingletonBeanRegistry(interface):管理单例bean的缓存接口,用于获取缓存池中的对象和向池子中注册对象
public interface SingletonBeanRegistry {
Object getSingleton(String beanName);
void registerSingleton(String beanName, Object singletonObject);
}
DefaultSingletonBeanRegistry(class):单例bean的缓存接口实现类,定义singletonObjects缓存池,实现注册和获取单例
public class DefaultSingletonBeanRegistry implements SingletonBeanRegistry{
/**
* 单例缓存池
* 根据 BeanDefinition 创建对象后才会放入单例池
*/
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>();
@Override
public Object getSingleton(String beanName) {
return singletonObjects.get(beanName);
}
@Override
public void registerSingleton(String beanName, Object singletonObject) {
singletonObjects.put(beanName, singletonObject);
}
}
SimpleBeanFactory(class):比较重要的一个类,用于组装bean的定义、注册bean的定义、管理单例缓存池等,他继承自 DefaultSingletonBeanRegistry (默认的单例缓存实现),实现了 BeanFactory 和 BeanDefinitionRegistry 接口。
public class SimpleBeanFactory extends DefaultSingletonBeanRegistry implements BeanFactory, BeanDefinitionRegistry {
/**
* 存放bean的定义(这里要和单例池区分开 不是一回事)
*/
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>();
@Override
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) {
beanDefinitionMap.put(beanName, beanDefinition);
}
@Override
public BeanDefinition getBeanDefinition(String beanName) {
BeanDefinition beanDefinition = beanDefinitionMap.get(beanName);
if (beanDefinition == null) {
throw new RuntimeException("No bean named '" + beanName + "' is defined");
}
return beanDefinition;
}
@Override
public boolean containsBeanDefinition(String beanName) {
return beanDefinitionMap.containsKey(beanName);
}
@Override
public Object getBean(String beanName) {
// 1. 先存缓存池中获取单例
Object singleton = getSingleton(beanName);
if (singleton != null) {
return singleton;
}
// 2. 如果bean还没有被创建 创建bean
BeanDefinition beanDefinition = getBeanDefinition(beanName);
return createBean(beanName, beanDefinition);
}
@Override
public <T> T getBean(String beanName, Class<T> requiredType) {
Object bean = getBean(beanName);
return requiredType.cast(bean);
}
private Object createBean(String beanName, BeanDefinition beanDefinition) {
try {
// 1. 创建bean实例
Class<?> beanClass = beanDefinition.getBeanClass();
Constructor<?> constructor = beanClass.getDeclaredConstructor();
constructor.setAccessible(true);
Object bean = constructor.newInstance();
// 2. 将bean实例注册到单例池中
registerSingleton(beanName, bean);
return bean;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
其实到这里我们的工作就完成了,捋清楚流程之后就特点简单了,然后我们写个测试类来测试一下。
public class SimpleBeanTest {
public static void main(String[] args) {
// 1. 获取容器工厂
SimpleBeanFactory simpleBeanFactory = new SimpleBeanFactory();
// 2. 注册bean定义
simpleBeanFactory.registerBeanDefinition("userService", new BeanDefinition(UserService.class));
// 3. 比较两个bean是否是同一个实例
UserService userService1 = simpleBeanFactory.getBean("userService", UserService.class);
UserService userService2 = simpleBeanFactory.getBean("userService", UserService.class);
userService1.test();
if (userService1 == userService2) {
System.out.println("两个bean是同一个实例, UserService 是单例的");
}
}
}
结果符合预期:

下一节我们要实现的是:如何实现自动注册+自动依赖注入,@Component、@Autowired 注解等。
One more thing
不要永远活在过去,未来可期。要及时放下执念,和过去说再见。
更多推荐
所有评论(0)