一、bean的生命周期
new–>注入–>setBeanId–>setBeanFactory–>setApplicationContext(获取其他bean)–>postProcessBeforeInitialization,修改bean–>init-method初始化–>postProcessAfterInitialization–>destory()–>destroy-method定制的销毁方法
-
实例化bean—new的过程
-
按照spring上下文对实例化的bean进行配置—IOC注入过程
-
若Bean实现了BeanNameAware接口,则调用setBeanName方法,传递的是spring配置文件的Bean的id
-
若Bean实现了BeanFactoryAware接口,则调用setBeanFactory方法,传递beanFactory的实例传入可以用这个方式来获取其它Bean,只需在Spring配置文件中配置一个普通的Bean就可以);
-
若Bean实现了ApplicationContext接口,则调用setApplicationContext方法,将bean所在的应用上下文传入(同样这个方式也可以实现步骤4的内容,但比4更好,因为ApplicationContext是BeanFactory的子接口,有更多的实现方法)
-
若Bean实现了BeanPostProcessor接口,则调用post-processBeforeInitialization方法。BeanPostProcessor经常被用作是Bean内容的更改,并且由于这个是在Bean初始化结束时调用那个的方法,也可以被应用于内存或缓存技术;
-
如果Bean在Spring配置文件中配置了init-method属性会自动调用其配置的初始化方法。
-
如果这个Bean关联了BeanPostProcessor接口,将会调用postProcessAfterInitialization(Object obj, String s)方法、
此时,bean的初始化过程完成,可以应用这个bean,是singleton的。当Bean不再需要时,会经过清理阶段, -
如果Bean实现了DisposableBean这个接口,会调用那个其实现的destroy()方法;
10.如果这个Bean的Spring配置中配置了destroy-method属性,会自动调用其配置的销毁方法。
二、spring的IOC初始化过程
主线:读取xml配置—>解析xml配置—>注册到BeanFactory
-
ClassPathXmlApplicationContext构造函数
- 设置xml文件资源
- 核心函数refresh()。实现IOC的初始化
-
ClassPathXmlApplicationContext的核心函数:refresh()为同步函数(synchronized代码块),
- 核心代码–作用创建beanFactory:ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(),BeanFactory的创建和Bean的解析都在该函数中进行。
-
ConfigurableListableBeanFactory核心函数:refreshBeanFactory函数。
- createBeanFactory()方法,创建BeanFactory,主要关注DefaultListableBeanFactory中的beanDefinitionMap成员变量,该变量用于后续存储bean相关数据
- 关键函数loadBeanDefinitions
三、springboot的启动过程
1、入口函数:SpringApplication.run(App.class),接收一个由@SpringBootApplication注解的配置类App.class,实现内容: 1、实例化SpringApplication的实例,2、调用实例方法run()。作为整个应用程序的起点。
- 1.1、实构造SpringApplication实例,实现了以下几个功能:
- (1)、计算当前的上下文类型(判断依据就是特定的上下文类是否存在)
- (2)、加载一批初始化器(初始化器是ApplicationContextInitializer的实现),用来对整个核心容器进行初始化操作
- (3)、加载一批监听器(监听器是ApplicationListener的实现),用来在初始阶段响应特定的容器事件以进行编程扩展,
- 1.2、调用SpringApplication.run()方法,实现以下功能:
- (1)、启动监听程序
- (2)、封装参数信息
- (3)、封装环境变量信息
- (4)、创建合适的applicationContext实例,需要定义出扫描bean定义的能力和从注解中解析bean定义的能力。
- 1.3、执行上下文的准备工作。
- (1)、完成环境变量的设置
- (2)、设置resourceLoader加载器
- (3)、应用初始化器,通知容器就绪事件,加载配置资源,执行load
- (4)、将所有通过注解、扫描、配置文件方式定义的bean都注册到上下文中去。通知load完成事件
- 1.4、执行刷新操作。调用了父类的refresh(AbstractApplicationContext定义,工厂方法)执行容器的刷新操作,是整个应用上下文启动的核心阶段,三大类:BeanFactory、Bean初始化、事件广播
- (1)、执行prepareRefresh执行刷新前的准备工作:更新应用上下文、初始化属性资源、验证配置文件
- (2)、初始化BeanFactory并配置,其子类可覆盖做额外处理;
- (3)、调用所有已添加的BeanFactoryPostProcessors,在bean的创建的前后,做定制化功能的扩展。
- (4)、初始化消息资源,初始化上下文事件多播机制,
- (5)、检查Bean中的监听器并注册到多播器中,
- (6)、实例化所有非懒加载的Bean到BeanFactory中.
- 1.5、执行刷新后的操作,清除缓存的资源,初始化生命周期处理器并触发容器刷新操作,多播容器刷新事件,至此容器刷新完成.
- 1.6、调用afterRefresh执行刷新后的操作,多播容器启动事件
- 1.7、回调CommandLineRunner,ApplicationRunner的Bean实现
- 1.8、多播上下文运行事件
四、BeanFactory与ApplicationContext
4.1、延迟加载:
- BeanFactroy采用的是延迟加载形式来注入Bean的,即**只有在使用到某个Bean时(调用getBean()),才对该Bean进行加载实例化,**这样,我们就不能发现一些存在的Spring的配置问题
- 而ApplicationContext则相反,它是在容器启动时,一次性创建了所有的Bean。这样,在容器启动时,我们就可以发现Spring中存在的配置错误。 相对于基本的BeanFactory,ApplicationContext 唯一的不足是占用内存空间。当应用程序配置Bean较多时,程序启动较慢。
4.2、BeanPostProcessor和BeanFactoryPostProcessor的使用
- BeanFactory需要手动注册,
- ApplicationContext则是自动注册。
总结
- BeanFactory是Spring的心脏,那么ApplicationContext就是完整的躯体了,ApplicationContext由BeanFactory派生而来,提供了更多面向实际应用的功能
- 在BeanFactory中,很多功能需要以编程的方式实现,而在ApplicationContext中则可以通过配置实现。
- BeanFactorty接口提供了配置框架及基本功能,但是无法支持spring的aop功能和web应用。
- ApplicationContext接口作为BeanFactory的派生,因而提供BeanFactory所有的功能,并有以下扩展功能:
- (1)MessageSource, 提供国际化的消息访问
- (2)资源访问,如URL和文件
- (3)事件传播特性,即支持aop特性
- (4)载入多个(有继承关系)上下文 ,使得每一个上下文都专注于一个特定的层次,比如应用的web层 ApplicationContext:是IOC容器另一个重要接口, 它继承了BeanFactory的基本功能, 同时也继承了容器的高级功能,如:MessageSource(国际化资源接口)、ResourceLoader(资源加载接口)、ApplicationEventPublisher(应用事件发布接口)等。
五、BeanFactory与FactoryBean
- BeanFactory,是个Factory,也就是IOC容器或对象工厂,是spring的核心,主要起创建和管理bean的作用
- FactoryBean,工厂类接口,用户可以通过实现该接口定制实例化Bean的逻辑。
- T getObject():
返回由FactoryBean创建的Bean实例,如果isSingleton()返回true,则该实例会放到Spring容器中单实例缓存池中; - boolean isSingleton():
返回由FactoryBean创建的Bean实例的作用域是singleton还是prototype; - Class getObjectType():
返回FactoryBean创建的Bean类型。
当配置文件中的class属性配置的实现类是FactoryBean时,通过getBean()方法返回的不是FactoryBean本身,而是FactoryBean#getObject()方法所返回的对象,相当于FactoryBean#getObject()代理了getBean()方法。
- T getObject():