手写一个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
不要永远活在过去,未来可期。要及时放下执念,和过去说再见。
