spring源码总结
spring源码总结
spring使用场景:编写登录功能。此功能由多个类的对象互相调用实现。一个对象调用另一个对象,Controller调用Service。不使用spring,Controller调用Service,调用之前需要UserService userService = new UserService()
spring源码做了什么:管理类的实例化对象
如何做的:
对不同对象的处理。
首先初始化的时候,即项目启动,加载所有的xml文件存为Bedifinition对象
- 非延迟加载的单例对象,初始化的时候new出来放在IOC容器中。
- 延迟加载的单例对象,第一次调用的时候new 出来放在IOC容器中。
- 多例对象,在使用时根据Bedifinition将对象new出来,返回给调用方。
AbstractApplicationContext定义了管理对象的流程。referesh有12个步骤.关键是第2步和第11步。
- 第2步加载xml配置文件为Bedifinition对象
- 创建IOC容器
DefaultListableBeanFactory - 加载解析XML文件,存到Document中
- 读取Document,处理为BeanDefinition
- 创建IOC容器
- 第11步根据Bedifinition中对Bean的定义,将bean new出来放在IOC容器中。
- finishBeanFactoryInitialization()
- preInstantiateSingletons(),判断抽象、单例、懒加载,FactoryBean。
- getBean()
- doGetBean
- creatBean
- doCreatBean
- creatBeanInstance(),默认使用无参构造函数生成Bean
- 放入三级缓存,用于解决循环依赖
- populateBean(),依赖注入(DI),填充属性
- initislizeBean(),调用初始化方法。(AOP发生在此步骤)
- DI
- AOP
- 第2步加载xml配置文件为Bedifinition对象
spring源码关键点:
FactoryBean与BeanFactory
BeanFactory,spring中的顶级接口。FactoryBean是工厂Bean。
三级缓存的理解
三级缓存扩展性更好。二级缓存可以解决循环依赖。但这意味着Bean在实例化之后就要完成AOP代理。而spring设计之初是通过AnnotationAwareAspectJAutoProxyCreator这个后置处理器在创建Bean的最后一步完成AOP代理。
一级缓存 singletonObjects
单例bean完成三部曲之后,会添加到一级缓存中。存储的是所有创建好了的单例Bean
二级缓存 earlySingletonObjects
二级缓存,完成实例化,但是还未进行属性注入及初始化的对象。
三级缓存 singletonFactories
提前暴露的一个单例工厂,二级缓存中存储的就是从这个工厂中获取到的对象.
循环依赖
如何产生:类A中有一个属性是B,类B中有一个属性是A。初始化A和B的时候,使用构造函数初始化,new A发现需要先new B,new B 发现要先new A。产生循环依赖。构造函数:A(B b){this.b = b}
1
2
3
4
5
6
7
8
9
10
11class A{
private B b;
public A(B b){this.b = b;}
}
class B{
private A a;
public B(A a){this.a = a;}
}如何解决:DI属性注入使用set,而不是构造函数。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27class A{
private B b;
public A(){}
public void setB(){
return b;
}
public B getB(){
this.b = b;
}
}
class B{
private A a;
public B(){}
public void setA(){
return a;
}
public A getA(){
this.a = a;
}
}生成A和B对象的流程。
- new A,放入缓存
- 依赖注入,set B
- new B,放入缓存
- 依赖注入,setA,从缓存中取出A,完成setA
- 从缓存拿出B,完成setB