Spring 源码(二)

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

 

图1i

图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对象。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值