1、Mini-spring 自己实现Spring注册、获取Bean

331 阅读4分钟

前言:

最近在学习 github上的项目mini-spring

github地址:mini-spring

很适合了解学习Spring框架原理的项目,感兴趣的可以给作者点点STAR

项目简介:

mini-spring是简化版的spring框架,能帮助你快速熟悉spring源码和掌握spring的核心原理。抽取了spring的核心逻辑,代码极度简化,保留spring的核心功能,如IoC和AOP、资源加载器、事件监听器、类型转换、容器扩展点、bean生命周期和作用域、应用上下文等核心功能。

作者的文档虽然没写那么多的解释,但是没有废话全是干货,搭配源码食用更佳。

mini-spring重点看懂第二个分支上的内容,也就是bean的注册和获取。后续都是基于这样的结构,所有在这个分支上花费的时间比较多,主要是搞懂调用继承关系,这样在扩展相关功能的时候都知道从何入手。

具体实现

1. 定义BeanDefinition

顾名思义,用于定义bean信息的类,包含bean的class类型、构造参数、属性值等信息,每个bean对应一个BeanDefinition的实例。简化BeanDefinition仅包含bean的class类型。

/**
 * BeanDefinition实例保存bean的信息,包括class类型、方法构造参数、是否为单例等,此处简化只包含class类型
 *
 */
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;
   }
}

2.定义BeanDefinitionRegistry接口

BeanDefinition注册表接口,定义注册BeanDefinition的方法。

/**
 * BeanDefinition注册表接口
 */
public interface BeanDefinitionRegistry {

   /**
    * 向注册表中注BeanDefinition
    *
    * @param beanName
    * @param beanDefinition
    */
   void registerBeanDefinition(String beanName, BeanDefinition beanDefinition);
}

3.定义Bean容器 BeanFactory

/**
 * bean容器
 */
public interface BeanFactory {

   /**
    * 获取bean
    *
    * @param name
    * @return
    * @throws BeansException bean不存在时
    */
   Object getBean(String name) throws BeansException;
}

4.定义SingletonBeanRegistry单例注册表

注册好对象后,放入单例注册表中,

5.定义实现Bean容器的抽象类AbstractBeanFactory。

这个抽象类中实现了getBean方法,并且提供了两个抽象方法,createBean()和getBeanDefinition().

所有在获取Bean的时候的步骤为:

1、先从单例注册表中获取Bean

2、获取不到的话,就通过获取BeanDefinition的方式获取BeanDefinition

3、获取到BeanDefinition后,再通过BeanDefinition去创建Bean,然后存入单例注册表中

public abstract class AbstractBeanFactory extends DefaultSingletonBeanRegistry implements BeanFactory {

   @Override
   public Object getBean(String name) throws BeansException {
      //先从单例注册表中获取
      Object bean = getSingleton(name);
      if (bean != null) {
         return bean;
      }
      //获取不到的话,就通过获取BeanDefinition的方式获取BeanDefinition(注册的时候存入的BeanDefinition)
      BeanDefinition beanDefinition = getBeanDefinition(name);
      //获取到BeanDefinition后,再通过BeanDefinition去创建Bean,然后存入单例注册表中
      return createBean(name, beanDefinition);
   }

   protected abstract Object createBean(String beanName, BeanDefinition beanDefinition) throws BeansException;

   protected abstract BeanDefinition getBeanDefinition(String beanName) throws BeansException;
}

6.定义AbstractBeanFactory 的子类AbstractAutowireCapableBeanFactory

重写createBean(),创建Bean然后注册。

public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory {

   @Override
   protected Object createBean(String beanName, BeanDefinition beanDefinition) throws BeansException {
      return doCreateBean(beanName, beanDefinition);
   }

   //通过反射的方式创建Bean
   protected Object doCreateBean(String beanName, BeanDefinition beanDefinition) {
      Class beanClass = beanDefinition.getBeanClass();
      Object bean = null;
      try {
         bean = beanClass.newInstance();
      } catch (Exception e) {
         throw new BeansException("Instantiation of bean failed", e);
      }

      addSingleton(beanName, bean);
      return bean;
   }
}

7.定义DefaultListableBeanFactory,我们真正调用的Bean容器。

Bean容器实现了BeanDefinitionRegistry,并且继承了AbstractAutowireCapableBeanFactory,所以同时具有了注册Bean和获取Bean的能力。

public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory implements BeanDefinitionRegistry {

   private Map<String, BeanDefinition> beanDefinitionMap = new HashMap<>();

   @Override
   public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) {
      beanDefinitionMap.put(beanName, beanDefinition);
   }

   @Override
   protected BeanDefinition getBeanDefinition(String beanName) throws BeansException {
      BeanDefinition beanDefinition = beanDefinitionMap.get(beanName);
      if (beanDefinition == null) {
         throw new BeansException("No bean named '" + beanName + "' is defined");
      }

      return beanDefinition;
   }
}

8.进行测试:

public class BeanDefinitionAndBeanDefinitionRegistryTest {

   @Test
   public void testBeanFactory() throws Exception {
      DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
      BeanDefinition beanDefinition = new BeanDefinition(HelloService.class);
      //注册Bean信息
      beanFactory.registerBeanDefinition("helloService", beanDefinition);
      //获取Bean。
      HelloService helloService = (HelloService) beanFactory.getBean("helloService");
      helloService.sayHello();
   }
}


public class HelloService {

   public String sayHello() {
      System.out.println("hello");
      return "hello";
   }
}

测试结果:

image.png

9.调用关系(重要)

下面来看一下具体的调用关系,这张图非常重要,很直观有助于我们一眼看清楚整体的设计。

image.png

10.要点分析:

AbstractBeanFactory

  • AbstractBeanFactory是DefaultSingletonBeanRegistry单例注册表的子类,具有从单例注册表中获取Bean,存储Bean的能力。

  • AbstractBeanFactory实现了BeanFactory的getBean()接口,而这个getBean()方法通过自身的两个抽象方法去实现,一个是getBeanDefinition()一个是createBean()。

    • getBeanDefinition() :获取BeanDefinition信息。放在我们真正调用的Bean容器DefaultListableBeanFactory中去实现(就是从注册的时候放进去的map中去取BeanDifiniton信息。)
    • createBean(): 获取到BeanDefinition信息后,通过BeanDefinition去创建Bean并存入单例注册表,放在抽象子类AbstractAutowireCapableBeanFactory中去实现。
    •   这两个方法一个放在Bean容器中实现,一个放在抽象子类中实现,分析这样设计的原因:createBean()方法是已经获取到了具体的BeanDefinition信息,直接通过反射的方式去创建Bean就可以了,所以放在抽象子类中当做默认的实现。

DefaultListableBeanFactory

DefaultListableBeanFactory作为bean容器,实现了BeanDefinitionRegistry,并且继承了AbstractAutowireCapableBeanFactory,所以同时具有了注册Bean和获取Bean的能力。

总结:

通过对mini-spring的bean-definition-and-bean-definition-registry分支代码分析,学习了如何自己实现Spring注册和获取Bean。但是项目中在实例化Bean的时候,通过beanClass.newInstance()来实例化,仅适用于bean有无参构造函数的情况。在下面的篇章中,我们继续学习mini-spring,学习其他实例化Bean的方式。