Spring 源码 八(无参构造方法,特殊构造方法如何实例化)

图1-0

Spring 源码 八(无参构造方法,特殊构造方法如何实例化)_第1张图片

图1-1

Spring 源码 八(无参构造方法,特殊构造方法如何实例化)_第2张图片

图1-2

Spring 源码 八(无参构造方法,特殊构造方法如何实例化)_第3张图片

图1-3

Spring 源码 八(无参构造方法,特殊构造方法如何实例化)_第4张图片

图1Spring 源码 八(无参构造方法,特殊构造方法如何实例化)_第5张图片

图2

Spring 源码 八(无参构造方法,特殊构造方法如何实例化)_第6张图片 图3

Spring 源码 八(无参构造方法,特殊构造方法如何实例化)_第7张图片

Spring 源码 八(无参构造方法,特殊构造方法如何实例化)_第8张图片

Spring 源码 八(无参构造方法,特殊构造方法如何实例化)_第9张图片

图4

Spring 源码 八(无参构造方法,特殊构造方法如何实例化)_第10张图片

Spring 源码 八(无参构造方法,特殊构造方法如何实例化)_第11张图片

此时的beanFactory是DefalutListableBeanFactory。所以执行这个类的preInterantiateSingletons()方法。 

图5

Spring 源码 八(无参构造方法,特殊构造方法如何实例化)_第12张图片

743行拿出所有的bd名称。

Spring 源码 八(无参构造方法,特殊构造方法如何实例化)_第13张图片

754 行判断是否有父的bd 。如果有父的bd。把父的bd和子的bd进行合并。图6 ,7,8,9,10举例说明。这个不重要,只有在xml中有这种写法。springBoot中已经淘汰了。例如index 不是抽象类,是单例,不是懒加载 会进第一个 if, 但是 index 没有包含& 所以不是 factoryBean .所以会进入下面的else分支中。

Spring 源码 八(无参构造方法,特殊构造方法如何实例化)_第14张图片

 接图11.

图6

Spring 源码 八(无参构造方法,特殊构造方法如何实例化)_第15张图片

图7

Spring 源码 八(无参构造方法,特殊构造方法如何实例化)_第16张图片图8

Spring 源码 八(无参构造方法,特殊构造方法如何实例化)_第17张图片

图9

Spring 源码 八(无参构造方法,特殊构造方法如何实例化)_第18张图片

图10

Spring 源码 八(无参构造方法,特殊构造方法如何实例化)_第19张图片

Spring 源码 八(无参构造方法,特殊构造方法如何实例化)_第20张图片

打印结果:

Spring 源码 八(无参构造方法,特殊构造方法如何实例化)_第21张图片

 这种子和父关系的orderService 在spring 中是怎么存的?会存两个示例,例如 order 和orderCjil 。这个两个示例的作用域,类名都一样。

作用域和类名是不是和bdmap有关系呢

t图11

图12

Spring 源码 八(无参构造方法,特殊构造方法如何实例化)_第22张图片

 

看上面注释。

Spring 源码 八(无参构造方法,特殊构造方法如何实例化)_第23张图片

那一种情况不为空呢,第二次调用的时候,或者是lazy的时候。 

Spring 源码 八(无参构造方法,特殊构造方法如何实例化)_第24张图片

 

Spring 源码 八(无参构造方法,特殊构造方法如何实例化)_第25张图片

sharredInstance不等于null的情况。

Spring 源码 八(无参构造方法,特殊构造方法如何实例化)_第26张图片

sharredInstance等于null的时候,如果是原型的话报错。判断我们正在创建的类是不是原型的。这段情况一般不会发生的,因为前面有判断是singleon的。  spring 在创建一个bean的时候,会往一个list中放一个beanName ,标识这个类正在创建。有一个属性currentlyInCreation表示正在创建。

Spring 源码 八(无参构造方法,特殊构造方法如何实例化)_第27张图片

Spring 源码 八(无参构造方法,特殊构造方法如何实例化)_第28张图片 Spring 源码 八(无参构造方法,特殊构造方法如何实例化)_第29张图片

Spring 源码 八(无参构造方法,特殊构造方法如何实例化)_第30张图片

因为只有我们设置了parentBeanFactory父类的工厂方法才会进这个代码,一般没有不重要。一般情况下是空。

Spring 源码 八(无参构造方法,特殊构造方法如何实例化)_第31张图片

 添加到aleradyCreated的set中标识已经创建了(图16)。不重要。

Spring 源码 八(无参构造方法,特殊构造方法如何实例化)_第32张图片

Spring 源码 八(无参构造方法,特殊构造方法如何实例化)_第33张图片 

Spring 源码 八(无参构造方法,特殊构造方法如何实例化)_第34张图片

获取bd。校验bd。  bd 中获取依赖dependsOn ,如果有依赖。率先示例化他的依赖。目前index没有依赖。所以为空。

Spring 源码 八(无参构造方法,特殊构造方法如何实例化)_第35张图片

如果是单例的调getSingleton 。index是单例的。所以今日362行  。注意这个getSingLeton和上次那个getSingLeton不一样。图19。 createBean() 图 21

Spring 源码 八(无参构造方法,特殊构造方法如何实例化)_第36张图片

Spring 源码 八(无参构造方法,特殊构造方法如何实例化)_第37张图片

 Spring 源码 八(无参构造方法,特殊构造方法如何实例化)_第38张图片

Spring 源码 八(无参构造方法,特殊构造方法如何实例化)_第39张图片

Spring 源码 八(无参构造方法,特殊构造方法如何实例化)_第40张图片

Spring 源码 八(无参构造方法,特殊构造方法如何实例化)_第41张图片

Spring 源码 八(无参构造方法,特殊构造方法如何实例化)_第42张图片

Spring 源码 八(无参构造方法,特殊构造方法如何实例化)_第43张图片

图13

Spring 源码 八(无参构造方法,特殊构造方法如何实例化)_第44张图片

图14

Spring 源码 八(无参构造方法,特殊构造方法如何实例化)_第45张图片

Spring 源码 八(无参构造方法,特殊构造方法如何实例化)_第46张图片

图15

Spring 源码 八(无参构造方法,特殊构造方法如何实例化)_第47张图片

图16

Spring 源码 八(无参构造方法,特殊构造方法如何实例化)_第48张图片

图17

Spring 源码 八(无参构造方法,特殊构造方法如何实例化)_第49张图片

Spring 源码 八(无参构造方法,特殊构造方法如何实例化)_第50张图片

图18

Spring 源码 八(无参构造方法,特殊构造方法如何实例化)_第51张图片

图19

 Spring 源码 八(无参构造方法,特殊构造方法如何实例化)_第52张图片

Spring 源码 八(无参构造方法,特殊构造方法如何实例化)_第53张图片 Spring 源码 八(无参构造方法,特殊构造方法如何实例化)_第54张图片

Spring 源码 八(无参构造方法,特殊构造方法如何实例化)_第55张图片

Spring 源码 八(无参构造方法,特殊构造方法如何实例化)_第56张图片

Spring 源码 八(无参构造方法,特殊构造方法如何实例化)_第57张图片

Spring 源码 八(无参构造方法,特殊构造方法如何实例化)_第58张图片

 

图20

Spring 源码 八(无参构造方法,特殊构造方法如何实例化)_第59张图片 

图20

Spring 源码 八(无参构造方法,特殊构造方法如何实例化)_第60张图片

两个getSingleton() 的区别。 第一个getSingleton()  == null 的时候,还要判断 isSingletonCurrentlyInCreation  判断这个类是不是正在创建,所以返回空。第二个getSingleton() 是经过各种densponsOn验证以后,并在set添加正在创建,如果为空则创建对象。使用new对象。而上一个主要用于beanFactory.getBean()。

图21

Spring 源码 八(无参构造方法,特殊构造方法如何实例化)_第61张图片

Spring 源码 八(无参构造方法,特殊构造方法如何实例化)_第62张图片

通过bd ,得到一个indexService这样的李。不重要。

Spring 源码 八(无参构造方法,特殊构造方法如何实例化)_第63张图片

lookup-menthod 和replace-method ,spring统称为method overriders 

Spring 源码 八(无参构造方法,特殊构造方法如何实例化)_第64张图片

如果在创建bean之前或者初始化之前, 通过执行后置处理器的前置方法,和后置方法如果能返回一个不为空的bean就直接返回,终止后续操作。不在示例化bean,和填充属性了,自动装配。

Spring 源码 八(无参构造方法,特殊构造方法如何实例化)_第65张图片

创建bean 。图 25

 图22

Spring 源码 八(无参构造方法,特殊构造方法如何实例化)_第66张图片

图23

Spring 源码 八(无参构造方法,特殊构造方法如何实例化)_第67张图片

如果你想返回的对象是一个广对象,不需要填充属性等操作,直接返回,就实现这个接口InstantiationAwareBeanPostProcessor

图24

Spring 源码 八(无参构造方法,特殊构造方法如何实例化)_第68张图片

InstantiationAwareBeanPostProcessor 这个类有三个方法,加上继承父类的一共有五个方法,我们可以随便实现那个方法,然后把对象new 出去返回,那么spring就不会做后续的实例化,填充属性的,没有任何依赖操作。主要是spring内部使用的。程序员使用无意义。InstantiationAwareBeanPostProcessor是内部后置处理器。 

图25

Spring 源码 八(无参构造方法,特殊构造方法如何实例化)_第69张图片

538行如果是单例,从factoryBeanInstanceCache,缓存中移除。

Spring 源码 八(无参构造方法,特殊构造方法如何实例化)_第70张图片 创建bean示例。

Spring 源码 八(无参构造方法,特殊构造方法如何实例化)_第71张图片

获取的instanceWrapper 对象,然后调用他的getWrappedInstance() 方法返回他的bean对象。 

Spring 源码 八(无参构造方法,特殊构造方法如何实例化)_第72张图片

Spring 源码 八(无参构造方法,特殊构造方法如何实例化)_第73张图片

图25-0

Spring 源码 八(无参构造方法,特殊构造方法如何实例化)_第74张图片

new 出来对象以后,首先放在singletonFactories这个map中一个,放registeredSingletons的list中一个。earlySingletonOjbects中移除。

图25-1

Spring 源码 八(无参构造方法,特殊构造方法如何实例化)_第75张图片

填充属性。

图26

Spring 源码 八(无参构造方法,特殊构造方法如何实例化)_第76张图片

Spring 源码 八(无参构造方法,特殊构造方法如何实例化)_第77张图片 不重要。

Spring 源码 八(无参构造方法,特殊构造方法如何实例化)_第78张图片

工厂方法。举例说明 图

Spring 源码 八(无参构造方法,特殊构造方法如何实例化)_第79张图片

Spring 源码 八(无参构造方法,特殊构造方法如何实例化)_第80张图片

 Spring 源码 八(无参构造方法,特殊构造方法如何实例化)_第81张图片

Spring 源码 八(无参构造方法,特殊构造方法如何实例化)_第82张图片

由后置处理器决定返回那些构造方法。如果是默认构造方法,spirng 的ctors返回空,默认没有构造方法 走无参构造方法。如果有一个有参的构造方法,ctors就不为空。走特殊构造方法逻辑。那么问题来了。假如 index里既有默认的无参构造器和有参构造器,spring ctors是为空还是不为空呢? 答案是为空。因为这个时候spirng 。 还有装配模型的必须是Autowire_constructor  详细图34。

如果有图40那种外部提供给spring 的构造方法和参数值的情况,下ctors 为1。但是用xml也是灭有值的。

Spring 源码 八(无参构造方法,特殊构造方法如何实例化)_第83张图片

这个是无参的构造法初始化图31。   特殊构造器初始化.图35

图27

IndexService ()方法。如果加了static 会IndexService会创建多次。如果不加会创建一次。为什么呢.图28标红处

图28

Spring 源码 八(无参构造方法,特殊构造方法如何实例化)_第84张图片

 

Spring 源码 八(无参构造方法,特殊构造方法如何实例化)_第85张图片

Spring 源码 八(无参构造方法,特殊构造方法如何实例化)_第86张图片

Spring 源码 八(无参构造方法,特殊构造方法如何实例化)_第87张图片 Spring 源码 八(无参构造方法,特殊构造方法如何实例化)_第88张图片

Spring 源码 八(无参构造方法,特殊构造方法如何实例化)_第89张图片

如果是static 设置为factoryMethode。相当于下面的xml形式。

Spring 源码 八(无参构造方法,特殊构造方法如何实例化)_第90张图片

图29

Spring 源码 八(无参构造方法,特殊构造方法如何实例化)_第91张图片

 图30

 

Spring 源码 八(无参构造方法,特殊构造方法如何实例化)_第92张图片

 Spring 源码 八(无参构造方法,特殊构造方法如何实例化)_第93张图片

lookup 在下次课。

Spring 源码 八(无参构造方法,特殊构造方法如何实例化)_第94张图片 首先从缓存中拿一个。因为我们没有往这个map中put。所以这个应该为空。

 

273行拿到了一个构造方法。

Spring 源码 八(无参构造方法,特殊构造方法如何实例化)_第95张图片

Spring 源码 八(无参构造方法,特殊构造方法如何实例化)_第96张图片  拿出构造方法,每次循环一次,nonSyntheticConstructors 加一次。

Spring 源码 八(无参构造方法,特殊构造方法如何实例化)_第97张图片

Spring 源码 八(无参构造方法,特殊构造方法如何实例化)_第98张图片

当前index他的注解为null不会进。

Spring 源码 八(无参构造方法,特殊构造方法如何实例化)_第99张图片

如果拿出的参数等于0的时候 ,让他成为一个默认的构造方法。

Spring 源码 八(无参构造方法,特殊构造方法如何实例化)_第100张图片

Spring 源码 八(无参构造方法,特殊构造方法如何实例化)_第101张图片

 循环完之后判断candidates是不是空。因为没有candidates.add()这个分支没有走,所以为空。

Spring 源码 八(无参构造方法,特殊构造方法如何实例化)_第102张图片 344行,如果有一个构造器并且构造器的参数的个数大于 0  ,有一个有参数的构造器返回。如果347行如果有两个构造器,并且在xml 设置了primary=true 的时候,defaultConstructor !=null。defaultConstructor 什么时候付的值呢,是在构造参数个数等于0的时候付的值。含有primary属性的构造器 和默认的的构造器的不一样的时候才会使用; 如果有一个默认构造器和一个无参构造如果不配置primary=true 当然也没有办法进这个分支,以下的分支也不成立最后null返回了。所以就用默认的构造器,无参构造器示例化。

Spring 源码 八(无参构造方法,特殊构造方法如何实例化)_第103张图片

Spring 源码 八(无参构造方法,特殊构造方法如何实例化)_第104张图片

如果是默认构造器,不走任何分支,返回空。

图31

Spring 源码 八(无参构造方法,特殊构造方法如何实例化)_第105张图片

jdk校验不重要。

Spring 源码 八(无参构造方法,特殊构造方法如何实例化)_第106张图片

无参构造器实例化。默认采用cglib的反射示例化策略。

图32

Spring 源码 八(无参构造方法,特殊构造方法如何实例化)_第107张图片

Spring 源码 八(无参构造方法,特殊构造方法如何实例化)_第108张图片

图33

Spring 源码 八(无参构造方法,特殊构造方法如何实例化)_第109张图片

Spring 源码 八(无参构造方法,特殊构造方法如何实例化)_第110张图片 Spring 源码 八(无参构造方法,特殊构造方法如何实例化)_第111张图片

80行得到默认的构造方法,及时把index 类的 所有构造方法删除,也可以得到这个默认的构造方法。

Spring 源码 八(无参构造方法,特殊构造方法如何实例化)_第112张图片

Spring 源码 八(无参构造方法,特殊构造方法如何实例化)_第113张图片

 实例化对象反射创建完成返回。

图34

Spring 源码 八(无参构造方法,特殊构造方法如何实例化)_第114张图片

Spring 源码 八(无参构造方法,特殊构造方法如何实例化)_第115张图片

Spring 源码 八(无参构造方法,特殊构造方法如何实例化)_第116张图片

Spring 源码 八(无参构造方法,特殊构造方法如何实例化)_第117张图片

pring 自动装配模型有, by_no,by_type,by_name;自动装配技术有@Autowrid @Resource ;spring 默认的自动装配模型是by_no,如果不加@Autowrid @Resource 注解时候,不自动装配。如果加了@Autowrid @Resource 才会自动装配。 如果是自动装配模型是by_type。加不加@Autowrid @Resource 都无所谓,只与set方法有关系,和属性和注解都没有关系。

图35

Spring 源码 八(无参构造方法,特殊构造方法如何实例化)_第118张图片

图36

Spring 源码 八(无参构造方法,特殊构造方法如何实例化)_第119张图片

图37

Spring 源码 八(无参构造方法,特殊构造方法如何实例化)_第120张图片

Spring 源码 八(无参构造方法,特殊构造方法如何实例化)_第121张图片

bw 中有个属性wrappedObject对象用来存储真是的对象。

Spring 源码 八(无参构造方法,特殊构造方法如何实例化)_第122张图片

constructorToUse决定使用哪个构造方法来示例化的对象。 argHolderToUse 构造方法需要哪些参数。

Spring 源码 八(无参构造方法,特殊构造方法如何实例化)_第123张图片

Spring 源码 八(无参构造方法,特殊构造方法如何实例化)_第124张图片

定义一个转化参数的变量argsToResolve. 134获取已经解析的构造方法。如果说这个构造方法已经解析完成,会赋值到resolvedConstructorOrFactoryMethod这个属性中。 他首先从这个属性中获取。如果不等于空从bd中获取参数给argToUser赋值。如果argsToResolve不为空进行解析。

Spring 源码 八(无参构造方法,特殊构造方法如何实例化)_第125张图片

Spring 源码 八(无参构造方法,特殊构造方法如何实例化)_第126张图片

如果传了构造方法,或者指定按自动装配解析。spring就要按构造方法装配.autowiring=true;

Spring 源码 八(无参构造方法,特殊构造方法如何实例化)_第127张图片

定义了构造方法参数值为空的一个局部变量。定义一个最小的参数个数,explicitArgs外面传进来的参数值,如果不为空最小的参数个数就是explicitArgs 的值。目前传过来的explicitArgs为空。

Spring 源码 八(无参构造方法,特殊构造方法如何实例化)_第128张图片

 

 Spring 源码 八(无参构造方法,特殊构造方法如何实例化)_第129张图片

 

Spring 源码 八(无参构造方法,特殊构造方法如何实例化)_第130张图片

如果有图40那种外部提供给spring 的构造方法和参数值的情况,下ctors 为1

Spring 源码 八(无参构造方法,特殊构造方法如何实例化)_第131张图片

为什么要定义Map和List 两种数据结构来存储呢参数值呢,?list 是用来存储无序的。Map是用来存储有序的。比如上图xml中,Map应该存储为 (0,arg);   外部可以通过标红出的方式传给spring 构造方法和参数值。cags 就是获取这种参数值。

Spring 源码 八(无参构造方法,特殊构造方法如何实例化)_第132张图片

确定构造方法的参数数量。minNrOfArgs 通过cags 获取这些外部值,如果cags有两个值,那么最小的参数值也应该有两个。

如果有图40那种外部提供给spring 的构造方法和参数值的情况,下minNrOfArgs 为1

Spring 源码 八(无参构造方法,特殊构造方法如何实例化)_第133张图片

把所有的构造方法赋值个candidates。不为空跳出

Spring 源码 八(无参构造方法,特殊构造方法如何实例化)_第134张图片

构造方法排序 先根据public 权限排序。再跟据参数个数排序。

Spring 源码 八(无参构造方法,特殊构造方法如何实例化)_第135张图片

定义了一个minTypeDiffWeight 最小类型差异变量 默认设置的是Integer的最大值。ambiguousConstructors 分歧变量。 

Spring 源码 八(无参构造方法,特殊构造方法如何实例化)_第136张图片

Spring 源码 八(无参构造方法,特殊构造方法如何实例化)_第137张图片

Spring 源码 八(无参构造方法,特殊构造方法如何实例化)_第138张图片

Spring 源码 八(无参构造方法,特殊构造方法如何实例化)_第139张图片

如果constructorToUse 不为空,证明 已经找到的合适的构造方法,那为什么不返回呢,因为他还要看下,下面是不是有更合适的构造方法, constructorToUse 不为空,那么argsToUse 参数的个数就是已经拿到的构造器的参数个数大于循环中的构造器参数个数就返回,因为再往下循环参数个数会越来越小,所以就没有必要再往下找了。break出去, 存放构造器这个list已经经过排序,最大的构造参数在上面,这样排序的。

 minNrOfArgs 通过cags 获取这些外部值,如果cags有两个值,那么最小的参数值也应该有两个。所以如果类型个数都小于最小参数个数,肯定要跳出本次循环。

Spring 源码 八(无参构造方法,特殊构造方法如何实例化)_第140张图片

Spring 源码 八(无参构造方法,特殊构造方法如何实例化)_第141张图片

加了@ConstructorProperties注解回去这里面的值,不重要。

Spring 源码 八(无参构造方法,特殊构造方法如何实例化)_第142张图片

这个拿到参数值然后放到paramNames中。

Spring 源码 八(无参构造方法,特殊构造方法如何实例化)_第143张图片

Spring 源码 八(无参构造方法,特殊构造方法如何实例化)_第144张图片

 

这个就是把上图xml中的order字符串类转化成 一个orderService类型。 可以把paramNames中的luban字符串转化成Luban的对象下图。

Spring 源码 八(无参构造方法,特殊构造方法如何实例化)_第145张图片

Spring 源码 八(无参构造方法,特殊构造方法如何实例化)_第146张图片

Spring 源码 八(无参构造方法,特殊构造方法如何实例化)_第147张图片

Spring 源码 八(无参构造方法,特殊构造方法如何实例化)_第148张图片

 

Spring 源码 八(无参构造方法,特殊构造方法如何实例化)_第149张图片

Spring 源码 八(无参构造方法,特殊构造方法如何实例化)_第150张图片 Spring 源码 八(无参构造方法,特殊构造方法如何实例化)_第151张图片

minTypeDiffWeight 默认是最大值。  typeDiffWeight 差异值,第一次typeDiffWeight < minTypeDiffWeight 值。

 

ambiguousConstructors存放差异值,如果构造器一样,差异一样 ,会存在 ambiguousConstructors这个种,放在最后抛出异常处理。

如果找到下一个差异值比这个更小,那么就清空ambiguousConstructors =null;

 Spring 源码 八(无参构造方法,特殊构造方法如何实例化)_第152张图片

constructorToUse肯定不为空。 

Spring 源码 八(无参构造方法,特殊构造方法如何实例化)_第153张图片

Spring 源码 八(无参构造方法,特殊构造方法如何实例化)_第154张图片 ambiguousConstructors存放差异值 异常处理。为什么找到两个相同的构造器一开始就抛异常,而是要等到遍历结束后统一抛异常处理呢,因为后面循环有可能找到一个更加匹配的。

Spring 源码 八(无参构造方法,特殊构造方法如何实例化)_第155张图片

 

 Spring 源码 八(无参构造方法,特殊构造方法如何实例化)_第156张图片

Spring 源码 八(无参构造方法,特殊构造方法如何实例化)_第157张图片 生成策略。Spring 源码 八(无参构造方法,特殊构造方法如何实例化)_第158张图片

示例化对象。

图38

Spring 源码 八(无参构造方法,特殊构造方法如何实例化)_第159张图片

 

图39

Spring 源码 八(无参构造方法,特殊构造方法如何实例化)_第160张图片 图40

图41

Spring 源码 八(无参构造方法,特殊构造方法如何实例化)_第161张图片

Spring 源码 八(无参构造方法,特殊构造方法如何实例化)_第162张图片

benaFactory.getBeanDefinition('index')

Spring 源码 八(无参构造方法,特殊构造方法如何实例化)_第163张图片

你可能感兴趣的:(spring)