接上文 Spring5源码 - 02 Bean和Java对象的区别与猜想验证BeanDefinition
我们分析了流程, 也从理论上描述了 普通对象 ----- BeanDefinition ------Bean对象之间的关联,提到了一个BeanDefinition的Map集合 (我们称之为 bdmap ,后面都用这个简称代替 ),
那从源码里面怎么体现出来bdmap 的呢?
本篇博文将带你一一掀开
因为这个bdmap 对应Spring太重要了,不仅要处理用户配置的扫描包下的bean,还有一点更重要Spring内置的bean 也需要依靠这个bdmap .
如果这个bdmap 完全交给开发者来处理,比如你把这个map中的数据给remove掉了,等等之类的不可信任的操作,结果可想而知,所以Spring封装了一些API,仅允许开发者通过Spring提供的API来修改bdmap .
那我们来看下Spring是如何来封装的这个API呢?
接上文中的 BeanFactoryPostProcessor Bean工厂后置处理器
ConfigurableListableBeanFactory 这个 beanFactory对象 是Spring封装的用于提供给开发者修改BeanDefinition的一个接口类。
提供了 getBeanDefinition 方法
beanFactory.getBeanDefinition("artisan1");
ctrl + alt + b 打开实现类 DefaultListableBeanFactory
我们来看下 定义 beanDefinitionMap
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);
Spring也是用的Map来存储的 ~
那我要看 spring是如何把BeanDefinition放到这个 beanDefinitionMap 中的,那我就需要重点观察 beanDefinitionMap 这个对象,Spring是在什么时候赋值的 .
我们知道了 DefaultListableBeanFactory 有个属性 是 beanDefinitionMap
先找DefaultListableBeanFactory
AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(AppConfig.class);
看下AnnotationConfigApplicationContetxt的类关系
跟进去构造函数
public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
this();
register(componentClasses);
refresh();
}
this();
【初始化BeanFactory】没有呢?我们知道实例化子类,父类也会被初始化,那往上找找吧
可以看到是在父类GenericApplicationContext中初始化的DefaultListableBeanFactory
这样的话,我们把断点打在下面一行 register(componentClasses)上,观察this 中的对象 如下
现在是有默认的Spring初始化的时候自己的BeanDefinition , 没有我们自己的bd ,那就继续走,看看这个beanDefinitionMap什么时候会发生变化~
先看结论
说明这一步就完成了 从 普通对象 ------- BeanDefinition ----------存入到 bdMap中的操作
接下来分析下核心源码
如上 ,这个流程完成后, DefaultListableBeanFactory#beanDefinitionMap 就有了new AnnotationConfigApplicationContext(AppConfig.class)
入参中的 AppConfig.class 对应的Bean了
那这个AppConfig配置的扫描包下的bean,什么时候初始化呢? 那就是refresh这个方法了 ,下文继续
先看一眼,结论
这个方法太重要了,一共有12个方法里面, 下篇博文 继续 分析