前言
Spring本质是一个bean工厂(beanFactory),它能按照我们的要求生产各种各样的bean,但是在生产过程中需要解决bean之间的依赖关系,引入了DI(依赖注入)。它能帮我们把bean之间做到松耦合,同时在生产bean的各个阶段对bean做额外的处理,Spring将这些阶段通过接口暴露给我们,只要我们让bean实现对应的接口,那么Spring就会在bean生命周期对应的阶段调用对应接口中的方法来处理该bean。
BeanFactory继承结构
- 四层接口
第一层接口:
BeanFactory,主要是getBean()方法
第二层接口:
HierarchicalBeanFactory,是为了实现bean工厂的层级关系提供支持。
AutowireCapableBeanFactory,提供自动装配bean能力的功能支持。
ListableBeanFactory,可以枚举所有的bean实例,是为了使客户端访问工厂中的bean而设计的。
第三层接口:
ConfigurableBeanFactory,继承HierarchicalBeanFactory并对它做了增强,还继承了另一个外来的接 口 SingletonBeanRegistry。
第四层接口:
ConfigurableListableBeanFactory,继承了ListableBeanFactory, AutowireCapableBeanFactory, ConfigurableBeanFactory,功能强大 - 三个实现类
1、AbstractBeanFactory:
继承了DefaultSingletonBeanRegistry,实现了ConfigurableListableBeanFactory接口,重写了getBean()方法,并在里面定义了两个个抽象方法getBeanDefinition()、createBean()
2、AbstractAutowireCapableBeanFactory:
继承了AbstractBeanFactory并且实现了AutowireCapableBeanFactory接口,实现了上面的抽象方法createBean(),里面主要是三个方法,bean的实例化-createBeanInstance()、bean的属性注入-populateBean()、bean的初始化-initializeBean()。
3、DefaultListableBeanFactory:
继承了AbstractAutowireCapableBeanFactory,同时实现了ConfigurableListableBeanFactory接口、BeanDefinitionRegistry接口。实现了上面的抽象方法getBeanDefinition(),其实也就是重写BeanDefinitionRegistry接口中的方法。它拥有这个继承体系中的所有功能。 - 两个外来接口
1、BeanDefinitionRegistry:
提供了对BeanDefinition的操作功能,比如注册、获取、移除等,实现类是DefaultListableBeanFactory。
2、SingletonBeanRegistry:
提供对单例bean的操作功能,比如注册、获取等,实现类是DefaultSingletonBeanRegistry。
bean的生命周期
-
容器的启动阶段
1、读取bean的xml,将xml文件中的每一个元素分别转换成一个BeanDefinition对象。
2、通过BeanDefinitionRegistry将这些bean注册到beanFactory中。
3、调用BeanFactoryPostProcessor接口的postProcessBeanFactory()方法。比如:PropertyPlaceholderConfigurer 将占位符替换成properties文件中具体的值。 -
bean生命周期----------对应AbstractAutowireCapableBeanFactory中的doCreateBean()方法;有四个阶段和多个扩展点。
bean生命周期及扩展点:
1、实例化-createBeanInstance
2、属性赋值-populateBean
3、初始化-initializeBean中的invokeInitMethods方法
4、销毁-DisposableBean接口的destroy()方法
第一个扩展点:
实例化前后会调用InstantiationAwareBeanPostProcessor的postProcessBeforeInstantiation和postProcessAfterInstantiation方法。
postProcessBeforeInstantiation:在doCreateBean()方法前处理的,如果该方法返回了一个实例对象,则直接返回该bean,用来代替通过内置的实例化流程创建对象。
postProcessAfterInstantiation:在populateBean()方法最开始处理,如果该方法返回了false,则不会继续进行属性注入。
第二个扩展点:
各种Aware标记接口:是在initializeBean()方法最开始处理
1、首先是BeanNameAware、BeanClassLoaderAware、BeanFactoryAware
第三个扩展点:
在初始化前后会调用BeanPostProcessor接口的postProcessBeforeInitialization和postProcessAfterInitialization方法
这两个处理都是在initializeBean方法中
第四个扩展点:
具体的初始化:
先在postProcessBeforeInitialization方法中会执行@PostConstruct注解的方法
再执行InitializingBean接口afterPropertiesSet方法,再执行自定义的init-method方法 -
整体流程:
1、调用InstantiationAwareBeanPostProcessor的postProcessBeforeInstantiation方法
2、实例化-createBeanInstance方法
3、调用InstantiationAwareBeanPostProcessor的postProcessAfterInstantiation方法
5、属性赋值-populateBean方法
6、Aware标记接口-BeanNameAware、BeanClassLoaderAware、BeanFactoryAware
7、调用BeanPostProcessor接口的postProcessBeforeInitialization方法(这里会处理@PostConstruct注解)
8、初始化-initializeBean中的invokeInitMethods方法,先执行InitializingBean接口afterPropertiesSet方法,再执行自定义的init-method方法
9、调用BeanPostProcessor接口的postProcessAfterInitialization方法(这里会处理@PreDestroy注解)
10、销毁 -
关于InitializingBean和DisposableBean
1、指定初始化方法有很多种,除了实现InitializingBean,还有XML方式,注解方式,没必要记住这几种的执行顺序,一般只会用一种。
2、DisposableBean类似于InitializingBean,对应生命周期的销毁阶段,以ConfigurableApplicationContext#close()方法作为入口,实现是通过循环取所有实现了DisposableBean接口的Bean然后调用其destroy()方法。
循环依赖
说明:
- 实例化完成后需要将对象通过ObjectFactory进行暴露,在ObjectFactory中有一个getObject方法,该方法中是调用了 getEarlyBeanReference 方法对bean做了一些后置处理(SmartInstantiationAwareBeanPostProcessor中的getEarlyBeanReference方法),返回处理完之后的bean。
- 从三级缓存中获取到ObjectFactory对象后,调用getObject方法(其实就是对bean做后置处理,也就是上述的getEarlyBeanReference 方法)获取提前暴露的bean,然后从三级缓存删除,加入到二级缓存中。
- bean初始化完成后,会从二级缓存和三级缓存中移除,加入到一级缓存中。
- 二级缓存和三级缓存的区别:
二级缓存只需要存储beanName和提前暴露的bean实例的映射关系即可;
三级缓存还需要对该bean做BeanPostProcessor后置处理。
思考:为什么需要三级缓存来完成呢,感觉二级缓存也能解决循环依赖?
- 第三级缓存主要是为了代理考虑的,为了AOP考虑的,AbstractAutoProxyCreator 这个类实现了
SmartInstantiationAwareBeanPostProcessor接口,并且在重写的
getEarlyBeanReference() 方法中返回了代理对象。 - 在发生循环依赖的时候,如果不使用三级缓存,我们就必须在A实例化完成后就给A创建代理对象,然后放回二级缓存中;而使用了三级缓存,则会在B中需要注入A的时候从三级缓存中获取A的时候才会给A创建代理对象并返回。这么一看两者确实没什么区别。
- 如果没有发生循环依赖,没有使用三级缓存时同样的还是会在A完成实例化的时候就给A生成代理对象了,这个和AOP的设计是不符合的;而使用了三级缓存,在对象初始化完成后,这时会调用 getSingleton() 方法,同样的是分别从一级、二级、三级缓存中去获取,此时肯定是在三级缓存中,并且在getObject()方法的时候完成了创建代理对象的过程,也就是说代理的创建是在整个Bean初始化完成之后的。
- 所以整体来看,这个第三级缓存存在的意义就在于为代理考虑的!
整体流程再梳理:
1、A实例化
将刚实例化完的A通过ObjectFactory进行暴露,放入三级缓存,对A做了一些后置处理(SmartInstantiationAwareBeanPostProcessor)
2、A属性赋值
A中有个属性是B对象,需要获取到B对象,getBean(B)
2.1、B实例化
2.2、B属性赋值
B中有个属性是A对象,需要获取A对象,getBean(A)
从缓存中获取A,此时实际是从3级缓存的ObjectFactory中调用getObject方法来获取bean,获取到之后将A转移到二级缓存中
2.3、B初始化
3、A初始化
BeanFactory和FactoryBean
- BeanFactory:工厂,是ioc容器的基础。可以管理和创建任意类型的对象。
- FactoryBean:特殊的Bean,实际返回的对象是重写的 getObject() 方法中返回的对象,一般针对一些复杂bean的创建。如果要获取的是FactoryBean本身的话,getBean()的时候 beanName前面用 ‘&'修饰。
- 有个经典的FactoryBean例子,就是 SqlSessionFactoryBean,它是mybatis整合Spring中的类。这个类就实现了FactoryBean,重写的getObject()方法中返回的就是 SqlSessionFactory。所以这个时候你获取的就不是 SqlSessionFactoryBean 本身,而是 SqlSessionFactory。同时这个类还实现了 InitializingBean 接口,重写了 afterPropertiesSet() 方法,在该方法中完成了对Mybatis的xml文件解析并得到一个 SqlSessionFactory。
BeanFactoryPostProcessor和BeanPostProcessor
- BeanFactoryPostProcessor:执行时机,在BeanDefinition未被用来创建对象之前,可以针对
BeanDefinition进行修改。比如PropertyPlaceholderConfigurer,就是用来判断BeanDefinition中是否有${},如果有就根据key去properties文件中获取到具体的value值并替换。 - BeanPostProcessor:执行时机,在Bean已经被实例化完成、属性赋值完成后,在bean初始化的时候被调用。初始化之前和初始化之后分别执行postProcessBeforeInitialization方法和postProcessAfterInitialization方法。