Spring中Bean的生命周期
- 实例化bean对象,并设置属性
- 检查Aware接口,并设置依赖
- 调用 BeanPostProcess的前置初始化方法postProcessBeforeInitialization()
- 调用InitializingBean的afterPropertiesSet()方法
- 调用自身init-method方法
- 调用 BeanPostProcess的后置初始化方法postProcessAfterInitialization()
- 完成创建- 使用
- 销毁
- 检查DisposableBean接口,若实现了则调用destroy销毁方法
- 若配置了destry-method属性,就调用这个配置的销毁方法
总的来说就是 实例化 — 属性赋值 — 初始化 — 销毁
- 单例模式下,容器启动时创建并初始化bean,容器关闭时销毁bean
- 多实例模式,容器启动时创建不创建bean,仅在bean被调用时创建和初始化bean,且不管理bean的销毁,即容器关闭时不会销毁bean。
Spring的执行(启动)流程
入口:AnnotationConfigApplicationContext
先了解几个概念
DefaultListableBeanFactory
: beanFactory 工厂
这个类有几个非常重要的属性:beanDefinitionMap是一个map,用来存放bean所对应的BeanDefinition;beanDefinitionNames是一个List集合,用来存放所有bean的name;singletonObjects是一个Map,用来存放所有创建好的单例Bean。BeanDefinition
对象: 它存储了 bean 对象的所有特征信息,如是否单例,是否懒加载,factoryBeanName 等AnnotatedBeanDefinitionReader
: 注解读取器ClassPathBeanDefinitionScanner
: 路径扫描器- refresh: 刷新容器(重点
- Spring中有很多后置处理器,但最终可以分为两种,一种是BeanFactoryPostProcessor,一种是BeanPostProcessor。前者的用途是用来干预BeanFactory的创建过程,后者是用来干预Bean的创建过程。后置处理器的作用十分重要,bean的创建以及AOP的实现全部依赖后置处理器。
执行流程
-
入口:AnnotationConfigApplicationContext的构造方法
1.1 构造函数中先调用了this(),调用了无参-
因为java继承,这里会先调用父类的无参构造方法
在父类的构造器中实例化了beanFactory,即直接new了一个DefaultListableBeanFactory。
-
this()中通过new AnnotatedBeanDefinitionReader(this)实例化了一个Bean读取器,并向BeanDefinitionMap中添加了7个元素。通过new ClassPathBeanDefinitionScanner(this)实例化了一个扫描器(该扫描器在后面并没有用到)。
this.reader = new AnnotatedBeanDefinitionReader(this);最后会调用到registerAnnotationConfigProcessors(BeanDefinitionRegistry registry,Object source)方法,这个方法会向BeanDefinitionMap中添加了7个类:
ConfigurationClassPostProcessor、AutowiredAnnotationBeanPostProcessor、CommonAnnotationBeanPostProcessor、RequiredAnnotationBeanPostProcessor、PersistenceAnnotationBeanPostProcessor、EventListenerMethodProcessor、DefaultEventListenerFactory
1.2 register(componentClasses)
将传入的配置类componentClasses解析成BeanDefinition(实际类型为AnnotatedGenericBeanDefinition),然后放入到BeanDefinitionMap中,这样后面在ConfigurationClassPostProcessor中能解析componentClasses1.3 refresh()
refresh()方法是整个Spring容器的核心,在这个方法中进行了bean的实例化、初始化、自动装配、AOP等功能。
在refresh()方法中,比较重要的方法为invokeBeanFactoryPostProcessors(beanFactory) 和 finishBeanFactoryInitialization(beanFactory)。
- postProcessBeanFactory(beanFactory)
空方法,由子类实现 - invokeBeanFactoryPostProcessors(beanFactory)
该方法的作用是执行所有的BeanFactoryPostProcessor
由于Spring会内置一个BeanFactoryPostProcessor,即ConfigurationClassPostProcessor(如果开发人员不自定义,默认情况下只有这一个BeanFactoryPostProcessor),这个后置处理器在处理时,会解析出所有交由Spring容器管理的Bean,将它们解析成BeanDefinition,然后放入到BeanFactory的BeanDefinitionMap中。 - registerBeanPostProcessors(beanFactory)
该方法的作用是找到所有的BeanPostProcessor,然后将这些BeanPostProcessor实例化 (会调用getBean()方法,getBean()方法的主要逻辑是:如果bean存在于BeanFactory中,则返回bean;如果不存在,则会去创建 ) 。将这些PostProcessor实例化后,最后放入到BeanFactory的beanPostProcessors属性中。
最后再重新注册了ApplicationListenerDetector,这样做的目的是为了将ApplicationListenerDetector放入到后置处理器的最末端。
registerBeanPostProcessor() 最终调用的是PostProcessorRegistrationDelegate.registerBeanPostProcessors()
从上面的源码中可以发现,BeanPostProcessor存在优先级,实现了PriorityOrdered接口的优先级最高,其次是Ordered接口,最后是普通的BeanPostProcessor。优先级最高的,会最先放入到beanPostProcessors这个集合的最前面,这样在执行时,会最先执行优先级最高的后置处理器(因为List集合是有序的)。
这样在实际应用中,如果我们碰到需要优先让某个BeanPostProcessor执行,则可以让其实现PriorityOrdered接口或者Ordered接口。
插个问题:如何找到所有的BeanPostProcessor? 包括Spring内置的和开发人员自定义的。
:由于在refresh()方法中,会先执行完invokeBeanFactoryPostProcessor()方法,这样所有自定义的BeanPostProcessor类均已经被扫描出并解析成BeanDefinition(扫描和解析又是谁做的呢?ConfigurationClassPostProcessor做的),存入至BeanFactory的BeanDefinitionMap,所以这儿能通过方法如下一行代码找出所有的BeanPostProcessor,然后通过getBean()全部实例化,最后再将实例化后的对象加入到BeanFactory的beanPostProcessors属性中,该属性是一个List集合。
String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);
- initMessageSource()
用来支持消息国际化,现在一般项目中不会用到国际化相关的知识。 - initApplicationEventMulticaster()
该方法初始化了一个事件广播器,如果容器中存在了beanName为applicationEventMulticaster的广播器,则使用该广播器;如果没有,则初始化一个SimpleApplicationEventMulticaster。
该事件广播器是用来做应用事件分发的,这个类会持有所有的事件监听器(ApplicationListener),当有ApplicationEvent事件发布时,该事件监听器能根据事件类型,检索到对该事件感兴趣的ApplicationListener。 - onRefresh()
执行其他的初始化操作,例如和SpringMVC整合时,需要初始化一些其他的bean,但是对于纯Spring工程来说,onRefresh()方法是一个空方法。 - registerListeners()
这一步会将自定义的listener的bean名称放入到事件广播器中,同时还会将早期的ApplicationEvent发布(对于单独的Spring工程来说,在此时不会有任何ApplicationEvent发布,但是和SpringMVC整合时,SpringMVC会执行onRefresh()方法,在这里会发布事件)。 - finishBeanFactoryInitialization(beanFactory)
该方法十分重要,它完成了所有非懒加载的单例Bean的实例化和初始化,属性的填充以及解决了循环依赖等问题。
主要流程为getBean() ——>doGetBean()——>createBean()——>doCreateBean()
在bean的创建过程中,一共出现了8次BeanPostProcessor的执行,在这些后置处理器的执行过程中,完成了AOP的实现、bean的自动装配、属性赋值等操作。 - finishRefresh()
执行到这一步,Spring容器的启动基本结束了,此时Bean已经被实例化完成,且完成了自动装配。执行finishRefresh()方法,是为了在容器refresh()结束时,做一些其他的操作,例如:发布ContextRefreshedEvent事件,这样当我们想在容器refresh完成后执行一些特殊的逻辑,就可以通过监听ContextRefreshedEvent事件来实现。
Spring内置了四个和应用上下文(ApplicationContextEvent)有关的事件:ContextRefreshedEvent、ContextStartedEvent、ContextStopedEvent、ContextClosedEvent。 - resetCommonCaches()
最后在refresh()方法的finally语句块中,执行了resetCommonCaches()方法。因为在前面创建bean时,对单例bean的元数据信息进行了缓存,而单例bean在容器启动后,不会再进行创建了,因此这些缓存的信息已经没有任何用处了,在这里进行清空,释放部分内存。
-