理解spring bean的生命周期对于细粒度的控制bean的创建、使用和销毁具有重要的意义,比如我们想要在一个bean创建之后做些额外的操作,合理的使用spring在生命周期中的调用方法,就可以轻易的完成这个任务,不过,首先,我们要理解bean在整个生命周期调用的方法链,才能正确的完成所需的功能。本文的目的是尝试使用实验的方式探索一个bean的生命周期。
我们首先创建一个bean类,它实现了InitializingBean,DisposableBean接口中的方法。
我们在spring配置文件中加载此bean,并且配置了init-method和destroy-method
在我们使用ClassPathXmlApplicationContext加载配置文件后,并在执行后使用close方法关闭ClassPathXmlApplicationContext后,得到如下输出
可见,在bean的生命周期里,构造方法首先被执行,然后如果有属性注入,则调用方法进行属性注入,属性注入完成后,PostConstruct注解的方法被执行,然后是InitializingBean的afterPropertiesSet方法被执行,而后,init-method方法的标签被执行,之后,bean就处于可被使用的状态。当调用了ClassPathXmlApplicationContext的close之后,则依次调用PreDestroy注解方法,DisposableBean的destroy方法,destroy-method标签中指定的方法。
总结一下,整个调用过程就是Constructor->Setter->PostConstruct->InitializingBean:AfterPropertiesSet->(init-method)->使用中->(容器关闭)->PreDestroy方法->Disposable:destroy方法->(destroy-method)。
其中PostConstruct,PreDestroy注解方法是javax中注解,可见jdk中的基础注解方法会在spring的方法之前调用,接着是InitializingBean和DisposableBean的方法会在标签方法之前执行。(PostConstruct,PreDestroy需要配置context:annotation-config)
理解了执行顺序,如果我们想在实例化之后进行一些操作,既可以使用PostConstruct注解方法,也可以使用InitializingBean中的方法。
加上BeanPostProcessor
如果我们实现了一个BeanPostProcessor的子类,并且将它注册在spring配置文件中,那么这个接口的postProcessBeforeInitialization和postProcessAfterInitialization方法会在属性注入之后(PostConstruct之后)和PreDestroy之前执行。这个类是全局的,也就是说它会在所有的bean实例化之后和销毁之前执行对应的方法。例如,我们注册了一个自定义的BeanPostProcessor。
注册该BeanPostProcessor,我们再次加载上面的bean,得到的结果是
也就是说会在属性注入后和销毁前环绕执行postProcessBeforeInitialization和postProcessAfterInitialization,那么如果有多个BeanPostProcessor,结果会是怎样呢,我们多注册一个MyBeanPostProcessor2,它的处理逻辑是一样的,只不过打印的头信息不同,输出结果编程这样
结论是依次按照配置文件里的顺序执行postProcessBeforeInitialization然后执行初始化后的方法,接着销毁前按顺序执行postProcessAfterInitialization,接着执行销毁方法。
有多个bean,那么BeanPostProcessor会环绕执行每一个bean。
xxxAware接口注入上下文相关对象
另外,Spring生命周期中还提供了注入上下文相关对象的接口,这种接口一般被命名为xxxAware,它们提供的对应的setter方法,将与上下文相关的信息在属性注入后注入到bean对象中使用,上下文相关的信息如:bean的名字,bean创建工厂,bean的上下文对象,这三个常用的上下文相关对象由BeanNameAware,BeanFactoryAware,ApplicationContextAware来完成,只要bean实现对应的接口方法,那么在属性注入后,spring就会将bean的名字(由id属性定义),创建工厂,上下文对象会分别传入这些方法。其中这三个方法的执行属性一次是setBeanName,setBeanFactory,setApplicationContext。ApplicationContext是基于BeanFactory实现的,提供了比建造工厂更多的功能,如读取xml配置文件,设置监听注册等等。
添加了这三个接口方法后,我们再执行,得到的结果是
总结
最后,总结整个spring bean的生命周期,可以将其分为四个大块:构造方法,属性注入,初始化方法,销毁方法。其中,属性注入的顺序是bean属性注入,BeanNameAware注入,BeanFactoryAware注入,ApplicationContextAware注入。初始化方法和销毁方法是一一对应的,如初始化方法的顺序是BeanPostProcessor的postProcessBeforeInitialization,javax注解PostConstruct,InitializingBean的afterPropertiesSet,标签方法init-method。
对应的BeanPostProcessor的postProcessAfterInitialization,javax注解preDestroy,DisposableBean的destroy,标签方法destroy-method。
参考文献
Spring点滴四:Spring Bean生命周期
SpringBean生命周期详解
Spring中
声明
本文首发表于我的博客,欢迎关注!已委托维权骑士为本站的文章进行维权,转载须注明文章出处,作者保留文章所有权。