相关文章

  • Spring 整体架构
  • 编译Spring5.2.0源码
  • Spring-资源加载
  • Spring 容器的初始化
  • Spring-AliasRegistry
  • Spring 获取单例流程(一)
  • Spring 获取单例流程(二)
  • Spring 获取单例流程(三)
  • Spring 循环依赖
  • Spring FactoryBean 缓存
  • Spring Aware 接口
  • Spring beanPostProcessor

大多数的方法都能从它的名字知道它是干啥的、都能在 XML 配置文件中找到对应的配置项

大部分的实现是落在 AbstractBeanDefinition 中、里面的逻辑也并不是特别的复杂、毕竟只是一些 get/set 方法

对于它的三个子类 GenericBeanDefinition RootBeanDefinition ChildBeanDefinition 其实本质上来说、它们并无太大的区别、它们都继承了 AbstractBeanDefinition 、在它们各自的类中、并没有什么太大的特殊的逻辑、某种程度上来说、它们可以说是差别非常小的

我们在 Spring 容器初始化的时候、读取 XML 配置文件并注册 BeanDefinition 、这个BeanDefinition 是子类中的哪个类呢

// 解释 bean 标签的时候BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
public static AbstractBeanDefinition createBeanDefinition(      @Nullable String parentName, @Nullable String className, @Nullable ClassLoader classLoader) throws ClassNotFoundException {   GenericBeanDefinition bd = new GenericBeanDefinition();   bd.setParentName(parentName);   if (className != null) {      if (classLoader != null) {         bd.setBeanClass(ClassUtils.forName(className, classLoader));      }      else {         bd.setBeanClassName(className);      }   }   return bd;}

最终它会落到这个工具类里面、创建的都是 GenericBeanDefinition

而在 BeanDefinitionRegistry 的实现类中、都是如此存储的

private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);

我们也是可以使用其他的 BeanDefinition 的子类注册

而我们在 getBean 的流程中的时候、当我们无法在三级缓存中获取到 bean 的时候、就开始了创建 bean 的流程、这个时候、就要从 beanDefinition 中获取相关信息创建 bean

final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);protected RootBeanDefinition getMergedLocalBeanDefinition(String beanName) throws BeansException {        // Quick check on the concurrent map first, with minimal locking.        RootBeanDefinition mbd = this.mergedBeanDefinitions.get(beanName);        if (mbd != null && !mbd.stale) {            return mbd;        }        return getMergedBeanDefinition(beanName, getBeanDefinition(beanName));    }

我们可以在 AbstractBeanFactory 中找到

private final Map<String, RootBeanDefinition> mergedBeanDefinitions = new ConcurrentHashMap<>(256);

可以看到 Map 中的 value 的类型是 RootBeanDefinition

如果你在定义中存在了父子 bean、或者更加具体的说、就是在 BeanDefinition 中、你的parentName 不为空、作为子 bean、你就要合成父 bean 的一些属性

synchronized (this.mergedBeanDefinitions) {    RootBeanDefinition mbd = null;    RootBeanDefinition previous = null;    if (containingBd == null) {    mbd = this.mergedBeanDefinitions.get(beanName);    }    if (mbd == null || mbd.stale) {    previous = mbd;    if (bd.getParentName() == null) {    // Use copy of given root bean definition.    if (bd instanceof RootBeanDefinition) {    mbd = ((RootBeanDefinition) bd).cloneBeanDefinition();    } else {    mbd = new RootBeanDefinition(bd);    }    } else {    // Child bean definition: needs to be merged with parent.    BeanDefinition pbd;    ......................    // Deep copy with overridden values.    mbd = new RootBeanDefinition(pbd);    mbd.overrideFrom(bd);    }    ........    if (containingBd == null && isCacheBeanMetadata()) {    this.mergedBeanDefinitions.put(beanName, mbd);    }    }    return mbd;}

貌似到目前为止、我们还是没有看到 ChildBeanDefinition 使用的场景

貌似确实没啥用是吧在整一个 Spring 框架中、我的版本 5.2

但是呢、其实我们可以手动的创建一个 BeanDefiniton 注册给 Spring

DefaultListableBeanFactory defaultListableBeanFactory = new DefaultListableBeanFactory();RootBeanDefinition rootBeanDefinition = new RootBeanDefinition();rootBeanDefinition.setBeanClass(Company.class);rootBeanDefinition.getPropertyValues().add("name", "XX");rootBeanDefinition.getPropertyValues().add("numberOfPeople", "1000");defaultListableBeanFactory.registerBeanDefinition("rootCompany", rootBeanDefinition);ChildBeanDefinition childBeanDefinition = new ChildBeanDefinition("rootCompany");defaultListableBeanFactory.registerBeanDefinition("childCompany", childBeanDefinition);System.out.println(defaultListableBeanFactory.getBean("rootCompany"));System.out.println(defaultListableBeanFactory.getBean("childCompany"));System.out.println(defaultListableBeanFactory.getBean("rootCompany") == defaultListableBeanFactory.getBean("childCompany"));

其实在 RootBeanDefinition 和 ChildBeanDefinition 中我们看到注释说、其实首选是 GenericBeanDefinition 、因为 RootBeanDefinition 不能够指定 parentName、而 ChildBeanDefinition 必须有 parentName、这在使用上是非常不灵活的

或许这就是 GenericBeanDefinition 出现的原因吧

在 AbstractAutowireCapableBeanFactory#doCreateBean 中

在创建好了一个 bean 的时候(不完整的 bean ),会对 MergedBeanDefinitionPostProcessor 的 postProcessMergedBeanDefinition 进行回调、这个时候是比加入第三级缓存之前早一点

defaultListableBeanFactory.addBeanPostProcessor(new MergedBeanDefinitionPostProcessor() {   @Override   public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {      System.out.println("beanName:" + beanName);   }});