讲解

首先来看看时序图,然后我们来讲解一下具体过程。
image.png
image.png
第一点,可以靠这个时序图大致摸清程序运行过程,接着我们直接DEBUG。
image.png
先看下图,这里就是主体方法实现,而我们直接运行,你会发现第一次调用,bean依然为空,当第二次调用你会发现bean就有值了。
第二点,认识模板模式。一个抽象类公开定义了执行它的方法的方式/模板。它的子类可以按需要重写方法实现,但调用将以抽象类中定义的方式进行。
可以查看这篇记录,模板方法模式
第三点,依靠模板模式设计Spring容器,使用两个Map对象来存放相同的对象。其中,一个Map使用单例模式,构建一个新的实例对象;一个Map使用模板模式,构建多个实例对象,存放Bean管理,这就是Spring Bean的原理。

实例

创建BeanFactory接口

  1. /**
  2. * BeanFactory是一个顶层接口,是最基本的Bean容器。
  3. * Spring使用BeanFactory来生成,配置和管理Bean。
  4. */
  5. public interface BeanFactory {
  6. Object getBean(String name) throws BeansException;
  7. }

创建Spring bean的建模对象

  1. /**
  2. * Spring bean的建模对象
  3. * BeanDefinition 用于保存 Bean 的相关信息,包括属性、构造方法参数、依赖的 Bean 名称及是否单例、延迟加载等,
  4. * 它是实例化 Bean 的原材料,Spring 就是根据 BeanDefinition 中的信息实例化 Bean。
  5. */
  6. public class BeanDefinition {
  7. /**
  8. * class基本信息:类型、包名
  9. */
  10. private Class beanClass;
  11. public BeanDefinition(Class beanClass) {
  12. this.beanClass = beanClass;
  13. }
  14. public Class getBeanClass() {
  15. return beanClass;
  16. }
  17. public void setBeanClass(Class beanClass) {
  18. this.beanClass = beanClass;
  19. }
  20. }

创建一个bean定义注册的接口

  1. public interface BeanDefinitionRegistry {
  2. /**
  3. * 向注册表中注册 BeanDefinition
  4. *
  5. * @param beanName
  6. * @param beanDefinition
  7. */
  8. void registerBeanDefinition(String beanName, BeanDefinition beanDefinition);
  9. }
  1. public interface SingletonBeanRegistry {
  2. Object getSingleton(String beanName);
  3. }
  1. public class BeansException extends RuntimeException {
  2. public BeansException(String msg) {
  3. super(msg);
  4. }
  5. public BeansException(String msg, Throwable cause) {
  6. super(msg, cause);
  7. }
  8. }

创建默认多对象工厂

  1. public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory implements BeanDefinitionRegistry {
  2. /**
  3. * Spring管理容器,注入的Bean是否放入Spring中
  4. */
  5. private Map<String, BeanDefinition> beanDefinitionMap = new HashMap<>();
  6. /**
  7. * 注册BeanDefinition中
  8. * @param beanName 注入bean的名字
  9. * @param beanDefinition 注入bean的定义
  10. */
  11. @Override
  12. public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) {
  13. beanDefinitionMap.put(beanName, beanDefinition);
  14. }
  15. /**
  16. * 获取bean的定义
  17. * @param beanName 注入bean的名字
  18. * @return 注入Bean的定义
  19. * @throws BeansException 没有注入Bean的异常
  20. */
  21. @Override
  22. public BeanDefinition getBeanDefinition(String beanName) throws BeansException {
  23. BeanDefinition beanDefinition = beanDefinitionMap.get(beanName);
  24. if (beanDefinition == null) throw new BeansException("No bean named '" + beanName + "' is defined");
  25. return beanDefinition;
  26. }
  27. }

创建抽象BeanFactory实现

  1. /**
  2. * 模板模式
  3. * 一个抽象类公开定义了执行它的方法的方式/模板。
  4. * 它的子类可以按需要重写方法实现,但调用将以抽象类中定义的方式进行。
  5. *
  6. * BeanDefinition 注册表接口
  7. */
  8. public abstract class AbstractBeanFactory extends DefaultSingletonBeanRegistry implements BeanFactory {
  9. /**
  10. * 在模板模式中这是主体方法,整体的自身方法都在这里调用
  11. * 获取单例Bean
  12. * @param name
  13. * @return
  14. * @throws BeansException
  15. */
  16. @Override
  17. public Object getBean(String name) throws BeansException {
  18. // 获取初始化的Bean
  19. Object bean = getSingleton(name);
  20. // Spring容器中的Bean存在,为单例Bean注入后,获取到的bean不为空的场合
  21. if (bean != null) {
  22. // 返回bean
  23. return bean;
  24. }
  25. // 获取bean的定义
  26. BeanDefinition beanDefinition = getBeanDefinition(name);
  27. // 返回一个实例化对象
  28. return createBean(name, beanDefinition);
  29. }
  30. /**
  31. * 在模板模式中这是按需方法,主体方法选择调用子方法
  32. * 获取bean的定义
  33. * @param beanName 注入bean的名字
  34. * @return 注入Bean的定义
  35. * @throws BeansException 没有注入Bean的异常
  36. */
  37. protected abstract BeanDefinition getBeanDefinition(String beanName) throws BeansException;
  38. /**
  39. * 在模板模式中这是按需方法,主体方法选择调用子方法
  40. * 创建实例化对象
  41. * @param beanName bean名字
  42. * @param beanDefinition bean定义
  43. * @return Spring容器中的实例化对象
  44. * @throws BeansException 该Bean不存在
  45. */
  46. protected abstract Object createBean(String beanName, BeanDefinition beanDefinition) throws BeansException;
  47. }

创建默认单例Bean注册

  1. /**
  2. * 在模板模式中,这里是模板方法,将用于构造整个单例事件
  3. * 默认单例Bean注册
  4. */
  5. public class DefaultSingletonBeanRegistry implements SingletonBeanRegistry {
  6. /**
  7. * 单例容器,存放初始化后的Bean
  8. * 第一次bean注册后,不再需要将Bean重复存放到Spring容器中
  9. * 第一次创建实例对象,验证注册成功后的Bean,使用Spring容器中的Bean调用方法
  10. * 第二次创建实例对象,直接使用单例模式下的对象调用方法
  11. */
  12. private Map<String, Object> singletonObjects = new HashMap<>();
  13. /**
  14. * 获取单例Bean
  15. *
  16. * @param beanName
  17. * @return
  18. */
  19. @Override
  20. public Object getSingleton(String beanName) {
  21. return singletonObjects.get(beanName);
  22. }
  23. /**
  24. * 注入单例Bean
  25. * @param beanName
  26. * @param singletonObject
  27. */
  28. protected void addSingleton(String beanName, Object singletonObject) {
  29. singletonObjects.put(beanName, singletonObject);
  30. }
  31. }

创建抽象自动装配BeanFactory中

  1. public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory {
  2. /**
  3. * 创建实例化对象
  4. * @param beanName bean名字
  5. * @param beanDefinition bean定义
  6. * @return Spring容器中的实例化对象
  7. * @throws BeansException 该Bean不存在
  8. */
  9. @Override
  10. protected Object createBean(String beanName, BeanDefinition beanDefinition) throws BeansException {
  11. Object bean = null;
  12. try {
  13. // 通过反射获取对象
  14. bean = beanDefinition.getBeanClass().newInstance();
  15. } catch (InstantiationException | IllegalAccessException e) {
  16. throw new BeansException("Instantiation of bean failed", e);
  17. }
  18. // 同时,将bean注入到单例容器中,防止重复创建实例对象,浪费资源
  19. addSingleton(beanName, bean);
  20. return bean;
  21. }
  22. }

最后测试类

  1. public class ApiTest {
  2. @Test
  3. public void test_BeanFactory(){
  4. // 1.初始化 BeanFactory
  5. DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
  6. // 2.注册 bean
  7. BeanDefinition beanDefinition = new BeanDefinition(UserService.class);
  8. beanFactory.registerBeanDefinition("userService", beanDefinition);
  9. // 3.第一次获取 bean
  10. UserService userService = (UserService) beanFactory.getBean("userService");
  11. userService.queryUserInfo();
  12. // 4.第二次获取 bean from Singleton
  13. UserService userService_singleton = (UserService) beanFactory.getBean("userService");
  14. userService_singleton.queryUserInfo();
  15. }
  16. }
  1. public class UserService {
  2. public void queryUserInfo(){
  3. System.out.println("查询用户信息");
  4. }
  5. }