我们知道bean的创建过程主要是getBean->doGetBean->createBean->doCreateBean

spring 有状态对象怎么设计_spring

开始进入源码,断点查看

spring 有状态对象怎么设计_创建对象_02

spring 有状态对象怎么设计_创建对象_03

spring 有状态对象怎么设计_spring 有状态对象怎么设计_04

 

spring 有状态对象怎么设计_创建对象_05

spring 有状态对象怎么设计_spring_06

先从缓存中获取单例对象getSingleton

spring 有状态对象怎么设计_spring 有状态对象怎么设计_07

并没有,直接返回

spring 有状态对象怎么设计_创建对象_08

spring 有状态对象怎么设计_原型模式_09

为指定的Bean标记为已经创建(或将要创建)

spring 有状态对象怎么设计_原型模式_10

下面将进入创建bean

spring 有状态对象怎么设计_创建对象_11

此处需要注意:ObjectFactory接口

spring 有状态对象怎么设计_spring 有状态对象怎么设计_12

先来看下ObjectFactory源码

spring 有状态对象怎么设计_spring_13

这个接口的定义非常简单,就是一个对象工厂,定义了一个返回对象的工厂方法。

ObjectFactory是一个普通的对象工厂接口。在AbstractBeanFacotry的doGetBean部分的源码中,可以看到spring对ObjectFactory的应用之一就是,

将创建对象的步骤封装到ObjectFactory中 交给自定义的Scope来选择是否需要创建对象来灵活的实现Scope。

通俗简单的说:

ObjectFactory就一个函数式接口,当调用其中的getObject方法的时候,才会将实际传递的匿名内部类中的实现逻辑来进行执行

spring 有状态对象怎么设计_spring_14

进入createBean方法了

spring 有状态对象怎么设计_spring_15

进入方法:锁定class,根据设置的class属性或者根据className来解析class

spring 有状态对象怎么设计_原型模式_16

spring 有状态对象怎么设计_spring 有状态对象怎么设计_17

spring 有状态对象怎么设计_spring_18

spring 有状态对象怎么设计_spring 有状态对象怎么设计_19

spring 有状态对象怎么设计_spring 有状态对象怎么设计_20

spring 有状态对象怎么设计_原型模式_21

根据类全限定字符串获取Class

spring 有状态对象怎么设计_原型模式_22

spring 有状态对象怎么设计_创建对象_23

接下来继续看:

spring 有状态对象怎么设计_创建对象_24

这里有个知识点说一下:

* spring中默认的对象都是单例的,spring会在一级缓存中持有该对象,方便下次直接获取,

* 那么如果是原型作用域的话,会创建一个新的对象

* 如果想在一个单例模式的bean下引用一个原型模式的bean,怎么办?

* 在此时就需要引用lookup-method标签来解决此问题

* 通过拦截器的方式每次需要的时候都去创建最新的对象,而不会把原型对象缓存起来

spring 有状态对象怎么设计_创建对象_25

spring 有状态对象怎么设计_spring_26

spring 有状态对象怎么设计_spring_27

进入doCreateBean方法了

spring 有状态对象怎么设计_原型模式_28

spring 有状态对象怎么设计_原型模式_29

spring 有状态对象怎么设计_原型模式_30

spring 有状态对象怎么设计_原型模式_31

spring 有状态对象怎么设计_spring_32

进入实例化

spring 有状态对象怎么设计_spring 有状态对象怎么设计_33

进入到使用的地方了

spring 有状态对象怎么设计_原型模式_34

spring 有状态对象怎么设计_spring_35

spring 有状态对象怎么设计_创建对象_36

spring 有状态对象怎么设计_spring_37

进入到动态代理

spring 有状态对象怎么设计_原型模式_38

spring 有状态对象怎么设计_spring_39

到这里就创建好了对象

spring 有状态对象怎么设计_创建对象_40

进入到获取getBean

spring 有状态对象怎么设计_原型模式_41


spring 有状态对象怎么设计_原型模式_42

spring 有状态对象怎么设计_spring 有状态对象怎么设计_43

spring 有状态对象怎么设计_创建对象_44

相当于是getBean("apple"),肯定是可以获取到了

spring 有状态对象怎么设计_原型模式_45

到这里还看不出lookup-method的作用

改下配置:

spring 有状态对象怎么设计_创建对象_46

继续查看,可以看到一级缓存中并没有apple对象

spring 有状态对象怎么设计_spring 有状态对象怎么设计_47

spring 有状态对象怎么设计_创建对象_48

开始getBean("apple")了

spring 有状态对象怎么设计_原型模式_49

可以看到进入了原型模式

spring 有状态对象怎么设计_创建对象_50

创建了对象1793

spring 有状态对象怎么设计_创建对象_51

spring 有状态对象怎么设计_spring 有状态对象怎么设计_52

spring 有状态对象怎么设计_原型模式_53

spring 有状态对象怎么设计_原型模式_54

创建对象1897,每次都是新的不同对象

spring 有状态对象怎么设计_spring 有状态对象怎么设计_55

如果到这里还是看不出来,再举个例子

spring 有状态对象怎么设计_spring 有状态对象怎么设计_56

spring 有状态对象怎么设计_创建对象_57

spring 有状态对象怎么设计_spring_58

spring 有状态对象怎么设计_spring 有状态对象怎么设计_59

是同一个对象吧

如果想解决这个问题也很简单

spring 有状态对象怎么设计_spring 有状态对象怎么设计_60

看结果:

spring 有状态对象怎么设计_spring 有状态对象怎么设计_61