图1
i
图1在执行 new AnnotationConfigApplicatIonContext() 的时候,首先调用 AnnotationConfigApplicationContext的父类GenericApplicationContext的 构造器,
图2

图3

GenericApplicationContext()构造器 会创建一个DefaultListablieBeanFactory()对象。赋值给beanFactory。 图4对DefaultListablieBeanFactory类进行详解。图4会对一些关键的属性进行解释。
图4



主要的dependencyComparator 工厂用来处理类的实例化的顺序。beanDefinitionMap 用来存储类的描述信息。 benDefinitionMap 是一个key为beanName,value为BeanDefinition类型的map.

beanDefinitionNames的List。这个list中存在的bean的名称.
图5


在 AnnotationConfigApplicationContext类里有一个属性reader(beanDefiainition简称bd,reader就是bd读取器),reader的作用是 把一个普通对象转换成beanDefainition对象(AnnotatedBeanDefinitionReader 只能读取加了注解的)。例如 reader可以把一个加了注解@Server的对象User 转换 成一个beanDefainition对象,为什么要转换成beanDefainition对象呢,因为beanDefainition对象是spirng用来描述一个bean的对象,类似java中用Class来描述一个对象。beanDefainitiion对象里包含了,是否是单例,是否是懒加载,是否加注解等等。那么user变成beanDefainition对象后,就表示他默认不是懒加载,是单例,是加了注解等等,是不是比class描述的更加全面了。
在new AnnotatedBeanDefinitionReader(tihis) (图6),这个this 代表当前对象AnnotationConfigApplicationContext对象,至少证明BeanDefinitionRegistry对象和 AnnotationConfigApplicationContext要么相当,要么存在父子关系BeanDefinitionRegistry 是父亲。
BeanDefinitionRegistry是一个bd的注册器. reader可以把一个user类转换成一个bd,但是需要通过beanDefinitionRegistry来放到beanDefinitionMap中。AnnotationConfigApplicationContext本身也充当一个注册器的角色。
图6

在构造器 又掉用有两个参数的构造器图7
图7

图7 给registry赋值,并委托给AnnotationConfigUtils来实现 利用registry来往beanDefintionMap中放bd.
图8

调用一个空壳方法,继续掉用图9
图9

其中 在此为 DefaultListableBeanFacory 类的DependencyComparator()属性赋值,dependencyComparator 工厂用来处理类的实例化的顺序,和 ContextAnnotationAutowireCandidateResover属性赋值。这个属性是延迟加载的。


判断registry是否包含图11这个类,第一次走的时候肯定没有,所以返回false,去false的!操作。进入if块中,RootBeanDefinition 是BeanDefinition的子类(表示是spring内部提供类)。通过构造器的方式转出成bd。例如 这个RootBeanDefinition类 就是把ConfigurationClassPostProcessor类型转换为RootBeanDefinition类型注册到BeanDefinitionMap中。
AutowiredAnnotationBeanPostProcessor,RequiredAnnotationBeanPostProcessor 和上个类型一样被注册到Map中。registerPostProcessor方法图12真正的通过registry的方法放进map中。
图10

其实可以理解是一个Map 为了方便传参。有传两个参数变为一个。简称bdh.
图11

图12

通过registry的registrerBeanDefinition()方法向beanDefinitionMap中put一个beanName和beanDefinition. 这个beanDefinition 是(ConfigurationClassPostProcessor)转换来的。最终返回一个BeanDefinitionHolder对象。
图13

这个scanner 就是能够扫描我们的类,包,并把我们的类或者包下的类转化成bd ,能够扫描bd,调用图14 。这个scanner暂时不做详解,后续会做。
图14

图14调用两个参数构造器图15
图15

调用三个构造器的图16
图16

图17

图18

注册一个Appconfig的一个配置类。也可以注册一个一个普通类。IndexDao.
图19

调用 图20;
图20

调用图21
图21


图21经过把传进来的类转换为bd。然后调用registerBeanDefinition() 方法把 bd放进beanDefinitionMap中去,图22.
图22

图23

图24


图25

可以看到整体结构,AnnotationConfigApplicatIonContext 包含scanner, beanFactory ( 包括beanDefinitionMap (包含Appconfigbd 和 剩余的6个类))
图26




总结图
图27


图28

图29


spring 提供一个接口来方便插手spring工厂的实例化过程。这个接口是BeanFactoryPostProcessor接口。图30举例说明.
图30


自定义一个MyBeanFactoryPostProcessor 类继承BeanFactoryPostProcessor接口,实现postProcessorBeanFactory方法。在方法中获取IndexDao类,并修改Scope为prototype。注意必须要加上注解@Componenet注解,来交给spring 管理。
图31

图32

在maim方法中比较dao和dao1两个hashCode的值,如果一样说明是单例的,如果不一样说明是prototype。
图32

打印结果证明是一样的,说明是prototype ,说明beanFactoryPostProcesstor 插手实例化成功。
图33

图34

refresh()方法 准备好工厂,实例化对象。 prepareRefresh() 。准备工作包括设置启动时间,是否激活标识位,初始化属性源配置。得到一个beanFactory工厂,为什么需要得到一个beanFactory工厂,因为需要对beanFactory工厂进行一些设置。

postProcessBeanFactory(beanFactory)后续版本会实现。

图35





1.添加一个类加载器,2.添加bean表达式解析器,为了能够让我们的beanFactory能够解析bean表达式.3。添加一个后置处理器,ApplicationContextAwareProcessor类型。 beanPostProcessor 是一个List ,能够插手bean实例化过程。目前springFactory只是维护了一个BeanPostProcessor的list的后置处理器,目前还没有用到。在bean实例化过程中会依次遍历执行list的后置处理器,来达到插手实例化的目的。4.添加自动注入被忽略的列表。5 ,registrerResolvableDependency 后续讲解。6. beanFactory添加一个ApplicationListenerDetector 的后置处理器,这个不重要。剩下的是spring的一些标准特征不重要。
图36

图37

图38

图36到38 不重要。
图39

getBeanFactoryPostProcessors() 获取自定义 BeanFactoryPostProcessors。 什么称为自定义的就是程序员自己写得,没有交给sping管理,更直白的说就是没有加上@Component注解的。
图40-1

图40-2

图40-1,图40-2 如果没有加@Component 获取BEANFactoryPostProcessors()的个数就为0; 如果我们想让他有个数咋办呢,去掉Component注解,然后在test类的main方法中 在refresh()方法前手动添加一个BeanFactoryPostProcessor()类。
图40-3

图40-4

现在这个

图40

图39调用图40 图40调用图41
图41

beanFactory 和BeanDefinitionRegistry 那么说工厂和AnnotationConfigApplicatIonContext 都是一个注册器。如果BeanFactory是一个BeanDefinitionRegistry,转换BeanFactory为一个BeanDefinitionRegistry 。 构建两个List 一个是regularPostProcessors 它包含BeanFactoryPostProcessor对象,另一个List是 registryProcessors 它包含BeanDefinitionRegistryPostProcessor对象。其中BeanDefinitionRegistryPostProcessor 也是一个BeanFactoryPostProcessor对象,因为他已经继承了BeanFactoryPostPRocessor对象。为什么要创建两个List? 通过上面分析,我们可以确定 当我们自定一个BeanFactoryPostProcessor的时候,可以有两种实现方式,第一个可以实现BeanDefinitionRegistryPostProcessor 接口,也可以实现他的父类BeanDefinitionRegistry接口,由此可以猜想出实现不同的接口需要实现不同的功能。其实也可以理解,BeanDefinitionRegistryPostProcessor是子类所以他一定扩展了BeanFactoryPostProcessor类。图42 。这样的好处就是不管我们实现那个接口。spring都能很好的解析。 如果实现了子接口就按子接口的方法执行,如果实现了父接口就按父接口执行。
图42

遍历自定义的beanFactoryPostProcessors list, 判断是否是BeanDefinitionRegistryPostProcessor ,因为自己实现的MyBeanFactoryProcessor是继承BeanFactoryPostProcessor 所以不是BeanDefinitionRegistryPostProcessor类型。会进入else逻辑。

会添加到regularPostProcessors的List中。

上面已经有一个registryProcessors 包含BeanDefinitionRegistryPostPRocessor元素的list了,为什么还要造一个currentRegistryProcessors呢?因为这个currentRegistryProcessors 是spring内部自己实现的。 beanFactory 通过getBeanFactoryPostProcessor() 这个方法 通过类型获取这个bd的名称。这里的type指的是bd 当中描述当前类的class类型。
再想一个问题,ConfigurationClassPostProcessor 这个类为什么在最开始就被放到beanDefinitionMap中取呢?因为需要在invokeBeanFactoryPostProcessors方法中调用。invokeBeanFactoryPostProcessors 方法主要是factory在初始化的过程中去做一些事情,什么事情呢,就是委托多个实现了BeanDefinitionRegistryPostProcessor接口或者BeanFactoryPostProcessor接口的类来做一些事情,有自定义的也有内部实现的,其中ConfigurationClassPostProcessor就是spring内部 的实现BeanDefinitionRegistryPostProcessor 接口的类,如果在最初不添加,这里就没有办法委托ConfigurationClassPostProcessor来做一些事情了。
首先根据Type 来获取beanDefinition的的bd的名称,postProcessorName 数组,遍历这个名字数组,依次根据名称拿出BeanDefinitionRegistryProstProcessor类型的bd,放在currentRegistryProcessors中取。

registryProcessors 它包含BeanDefinitionRegistryPostProcessor 对象的List ,目前只包含有可能是用户自定义的去实现了BeanDefinitionRegistryPostProcessor 接口的类,registryProcessors再把spring内部实现了BeanDefinitionRegistryPostProcessor接口的类添加进去。也就是合并List, 调用这个 invokeBeanDefinitionRegistyPostProcessors方法的意义是什么 图44
合并完后清除 currentRegistryProcessors的List .
。图42

图43

图44

依次把传进来的BeanDefinitionRegistryPostProcessor List 进行遍历遍历调用 BeanDefinitionRegistryPostProcessor 类的postProcessBeanDefinitionRegistry 这个类是扩展方法。图45-1 。也就是说目前spring 的扩展点有三个.一个是BeanPostProcessor, 还有一个是BeanFactoryPostProcessor。还有一个就是BeanDefinitionRegistryPostProcessor。
图45-1

图45

ConfigurationClassPostProcessor 继承了BeanDefinitionRegistryPostProcessor 的,所以调用了他重写父类的postProcessBeanDefinitionRegistry() 的方法。调用processConfigBeanDefinitions() 图46 的方法。
图46

获取所有的在beanMapDefinitionMap中的beanName
遍历这7个bean, 判断是否处理过。

判断是否有@Configuration ,判断是否加@Component,@ImportResurce,@CompentScan @ImprtResource,如果加了在configCandidates 的List中添加一个BeanDefinitionHolder().

如图51如果 appCofing类有多个,那么可以排序。获取@Order注解的顺序号依次排序。


获的bean的容器生成器,判断外部是不是提供生成器,如果没有提供默认使用spring自己的。并且赋值



定义了两个变量用于去重。parser.parse() 来解析这个candidates



把扫描出的bean(indexDao) 类添加到beanMapDefinitionMap 中。

图47

从beanDefinitionMap 中获取所以注册的bean名称。
图48


判断是否是AnnotatedBeanDefinition 类,如果是强转为AnnotatedBeanDefinition类,获取元数据。

判断不是AnnotatedBeanDefinition 类,如果是new SttandardAnnotationMetadata类,获取元数据。




判断是否加@Component,@ImportResurce,@CompentScan @ImprtResource,如果加了,设置属性为ConfiglRatION_CLASS_LITE

图49

判断是否加了Configuration注解,如果加了。

图50




图51

图52


图53

图54



图55

进行一个类的封装。
图56

图55对应的方法 处理内部类,一般不会有内部类



解析componentScan注解。
图56



图57



通过调用registerBeanDefinition(definitionHolder,this,registry)方法,
图58-0


图58-1


把 bd 注册到beanDefinitionMap中。
图58

图59


通过new ScannedGenericBeanDefinition对象,把bean转换成ScannedGenericBeanDefinition 对象,他的父类也是BeanDefinition对象。


本文深入剖析Spring框架中Bean的实例化流程,从AnnotationConfigApplicationContext的构造开始,详细解读了BeanDefinition的注册、BeanFactoryPostProcessor的使用及Bean实例化过程中的关键步骤。
1271

被折叠的 条评论
为什么被折叠?



