深入学习Spring Bean生命周期 一、前言所谓Spring Bean的生命周期指的是Bean从创建到初始化再到销毁的过程这个过程由IOC容器管理这里我们主要记录一些和Bean生命周期相关的细节。二、Bean的初始化和销毁在整个生命周期过程中我们可以自定义Bean的初始化和销毁钩子函数当Bean的生命周期到达相应的阶段的时候Spring会调用我们自定义的Bean的初始化和销毁方法。自定义Bean初始化和销毁方法有多种方式下面逐一介绍。2.1 Bean注册上一节《深入学习Spring组件注册》中介绍了可以在配置类中通过Bean注解来注册Bean我们也可以通过它来指定Bean的初始化和方法。为了演示我们新建一个Spring Boot项目然后创建一个User类publicclassUser{publicUser(){System.out.println(User 无参构造函数);}publicvoidinit(){System.out.println(初始化User);}publicvoiddestory(){System.out.println(销毁User);}}然后在配置类里注册该组件并指定初始化和销毁方法ConfigurationpublicclassWebConfig{Bean(initMethodinit,destroyMethoddestory)publicUseruser(){returnnewUser();}}其中initMethod init和destroyMethod destory与User类里的initdestory方法相对应。在Spring Boot测试类中增加测试:RunWith(SpringRunner.class)SpringBootTestpublicclassBeanLifeCycleApplicationTests{Testpublicvoidtest(){AnnotationConfigApplicationContextcontextnewAnnotationConfigApplicationContext(WebConfig.class);System.out.println(容器创建完毕);Userusercontext.getBean(User.class);// 关闭 IOC 容器context.close();}}启动测试类观察控制台输出:User 无参构造函数初始化User容器创建完毕销毁User从上面的输出我们看出在容器启动之前先调用对象的无参构造器创建对象然后调用初始化方法在容器关闭的时候调用销毁方法。上面的情况是对于单例而言的如果组件是多例模式又是什么情况呢我们把上面的组件注册配置改为多例然后再次启动项目观察控制台输出:User 无参构造函数初始化User容器创建完毕销毁User控制台的输出和我们上节讨论的一致即在多例模式下IOC容器启动的时候并不会去创建对象而是在每次获取的时候才会去调用方法创建对象创建完对象后再调用初始化方法。但在容器关闭后Spring并没有调用相应的销毁方法这是因为在多例模式下容器不会管理这个组件只负责在你需要的时候创建这个组件所以容器在关闭的时候并不会调用相应的销毁方法。2.2 nitializingBeanDisposableBean除了上面这种方式指定初始化和销毁方法外Spring还为我们提供了和初始化销毁相对应的接口1.InitializingBean接口包含一个afterPropertiesSet方法我们可以通过实现该接口然后在这个方法中编写初始化逻辑。2.DisposableBean接口包含一个destory方法我们可以通过实现该接口然后再这个方法中编写销毁逻辑。新建一个类名称为Dept然后实现这两个接口publicclassDeptimplementsInitializingBean,DisposableBean{publicDept(){System.out.println(Dept 无参构造函数);}Overridepublicvoiddestroy()throwsException{System.out.println(销毁Dept);}OverridepublicvoidafterPropertiesSet()throwsException{System.out.println(初始化Dept);}}在配置类中注册这个组件:BeanpublicDeptdept(){returnnewDept();}测试一波RunWith(SpringRunner.class)SpringBootTestpublicclassBeanLifeCycleApplicationTests{Testpublicvoidtest(){AnnotationConfigApplicationContextcontextnewAnnotationConfigApplicationContext(WebConfig.class);System.out.println(容器创建完毕);// 关闭 IOC 容器context.close();}}启动测试类观察控制台输出:Dept 无参构造函数初始化Dept容器创建完毕销毁Dept2.3 PostConstructPreDestroy除了上面两种指定初始化和销毁方法的方式外我们还可以使用PostConstruct和PreDestroy注解修饰方法来指定相应的初始化和销毁方法。新建一个类名称为MenupublicclassMenu{publicMenu(){System.out.println(Menu 无参构造函数);}PostConstructpublicvoidinit(){System.out.println(初始化Menu);}PreDestroypublicvoiddestory(){System.out.println(销毁Menu);}}在配置类中注册这个组件:BeanpublicMenumenu(){returnnewMenu();}测试一波RunWith(SpringRunner.class)SpringBootTestpublicclassBeanLifeCycleApplicationTests{Testpublicvoidtest(){AnnotationConfigApplicationContextcontextnewAnnotationConfigApplicationContext(WebConfig.class);System.out.println(容器创建完毕);// 关闭 IOC 容器context.close();}}启动测试类观察控制台输出:Menu 无参构造函数初始化Menu容器创建完毕销毁Menu效果和上面两种方式一致。注意:这两个注解并非Spring提供而是JSR250规范提供。三、BeanPostProcessorSpring提供了一个BeanPostProcessor接口俗称Bean后置通知处理器它提供了两个方法postProcessBeforeInitialization和postProcessAfterInitialization。其中postProcessBeforeInitialization在组件的初始化方法调用之前执行postProcessAfterInitialization在组件的初始化方法调用之后执行。它们都包含两个入参1.bean当前组件对象 2.beanName当前组件在容器中的名称。两个方法都返回一个Object类型我们可以直接返回当前组件对象或者包装后返回。我们来定义一个BeanPostProcessor接口的实现类MyBeanPostProcessorpublicclassMyBeanPostProcessorimplementsBeanPostProcessor{OverridepublicObjectpostProcessBeforeInitialization(Objectbean,StringbeanName)throwsBeansException{System.out.println(beanName 初始化之前调用);returnbean;}OverridepublicObjectpostProcessAfterInitialization(Objectbean,StringbeanName)throwsBeansException{System.out.println(beanName 初始化之后调用);returnbean;}}在配置类中注册该组件:BeanpublicMyBeanPostProcessormyBeanPostProcessor(){returnnewMyBeanPostProcessor();}再次启动测试类观察控制台输出:beanLifeCycleApplication 初始化之前调用beanLifeCycleApplication 初始化之后调用User 无参构造函数user 初始化之前调用初始化Useruser 初始化之后调用Dept 无参构造函数dept 初始化之前调用初始化Deptdept 初始化之后调用Menu 无参构造函数menu 初始化之前调用初始化Menumenu 初始化之后调用org.springframework.boot.autoconfigure.AutoConfigurationPackages 初始化之前调用org.springframework.boot.autoconfigure.AutoConfigurationPackages 初始化之后调用org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration 初始化之前调用org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration 初始化之后调用org.springframework.boot.autoconfigure.jmx.JmxAutoConfiguration 初始化之前调用org.springframework.boot.autoconfigure.jmx.JmxAutoConfiguration 初始化之后调用objectNamingStrategy 初始化之前调用objectNamingStrategy 初始化之后调用mbeanServer 初始化之前调用mbeanServer 初始化之后调用mbeanExporter 初始化之前调用mbeanExporter 初始化之后调用org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration 初始化之前调用org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration 初始化之后调用springApplicationAdminRegistrar 初始化之前调用springApplicationAdminRegistrar 初始化之后调用org.springframework.boot.autoconfigure.aop.AopAutoConfigurationC l a s s P r o x y i n g C o n f i g u r a t i o n 初始化之前调用 o r g . s p r i n g f r a m e w o r k . b o o t . a u t o c o n f i g u r e . a o p . A o p A u t o C o n f i g u r a t i o n ClassProxyingConfiguration 初始化之前调用 org.springframework.boot.autoconfigure.aop.AopAutoConfigurationClassProxyingConfiguration初始化之前调用org.springframework.boot.autoconfigure.aop.AopAutoConfigurationClassProxyingConfiguration 初始化之后调用org.springframework.boot.autoconfigure.aop.AopAutoConfiguration 初始化之前调用org.springframework.boot.autoconfigure.aop.AopAutoConfiguration 初始化之后调用org.springframework.boot.autoconfigure.availability.ApplicationAvailabilityAutoConfiguration 初始化之前调用org.springframework.boot.autoconfigure.availability.ApplicationAvailabilityAutoConfiguration 初始化之后调用applicationAvailability 初始化之前调用applicationAvailability 初始化之后调用org.springframework.boot.autoconfigure.context.ConfigurationPropertiesAutoConfiguration 初始化之前调用org.springframework.boot.autoconfigure.context.ConfigurationPropertiesAutoConfiguration 初始化之后调用org.springframework.boot.context.properties.BoundConfigurationProperties 初始化之前调用org.springframework.boot.context.properties.BoundConfigurationProperties 初始化之后调用org.springframework.boot.context.properties.ConfigurationBeanFactoryMetadata 初始化之前调用org.springframework.boot.context.properties.ConfigurationBeanFactoryMetadata 初始化之后调用org.springframework.boot.autoconfigure.context.LifecycleAutoConfiguration 初始化之前调用org.springframework.boot.autoconfigure.context.LifecycleAutoConfiguration 初始化之后调用spring.lifecycle-org.springframework.boot.autoconfigure.context.LifecycleProperties 初始化之前调用spring.lifecycle-org.springframework.boot.autoconfigure.context.LifecycleProperties 初始化之后调用lifecycleProcessor 初始化之前调用lifecycleProcessor 初始化之后调用spring.info-org.springframework.boot.autoconfigure.info.ProjectInfoProperties 初始化之前调用spring.info-org.springframework.boot.autoconfigure.info.ProjectInfoProperties 初始化之后调用org.springframework.boot.autoconfigure.info.ProjectInfoAutoConfiguration 初始化之前调用org.springframework.boot.autoconfigure.info.ProjectInfoAutoConfiguration 初始化之后调用org.springframework.boot.autoconfigure.task.TaskExecutionAutoConfiguration 初始化之前调用org.springframework.boot.autoconfigure.task.TaskExecutionAutoConfiguration 初始化之后调用spring.task.execution-org.springframework.boot.autoconfigure.task.TaskExecutionProperties 初始化之前调用spring.task.execution-org.springframework.boot.autoconfigure.task.TaskExecutionProperties 初始化之后调用taskExecutorBuilder 初始化之前调用taskExecutorBuilder 初始化之后调用org.springframework.boot.autoconfigure.task.TaskSchedulingAutoConfiguration 初始化之前调用org.springframework.boot.autoconfigure.task.TaskSchedulingAutoConfiguration 初始化之后调用spring.task.scheduling-org.springframework.boot.autoconfigure.task.TaskSchedulingProperties 初始化之前调用spring.task.scheduling-org.springframework.boot.autoconfigure.task.TaskSchedulingProperties 初始化之后调用taskSchedulerBuilder 初始化之前调用taskSchedulerBuilder 初始化之后调用spring.devtools-org.springframework.boot.devtools.autoconfigure.DevToolsProperties 初始化之前调用spring.devtools-org.springframework.boot.devtools.autoconfigure.DevToolsProperties 初始化之后调用org.springframework.boot.devtools.autoconfigure.LocalDevToolsAutoConfigurationR e s t a r t C o n f i g u r a t i o n 初始化之前调用 o r g . s p r i n g f r a m e w o r k . b o o t . d e v t o o l s . a u t o c o n f i g u r e . L o c a l D e v T o o l s A u t o C o n f i g u r a t i o n RestartConfiguration 初始化之前调用 org.springframework.boot.devtools.autoconfigure.LocalDevToolsAutoConfigurationRestartConfiguration初始化之前调用org.springframework.boot.devtools.autoconfigure.LocalDevToolsAutoConfigurationRestartConfiguration 初始化之后调用fileSystemWatcherFactory 初始化之前调用fileSystemWatcherFactory 初始化之后调用restartingClassPathChangedEventListener 初始化之前调用restartingClassPathChangedEventListener 初始化之后调用classPathRestartStrategy 初始化之前调用classPathRestartStrategy 初始化之后调用classPathFileSystemWatcher 初始化之前调用classPathFileSystemWatcher 初始化之后调用conditionEvaluationDeltaLoggingListener 初始化之前调用conditionEvaluationDeltaLoggingListener 初始化之后调用org.springframework.boot.devtools.autoconfigure.LocalDevToolsAutoConfigurationL i v e R e l o a d C o n f i g u r a t i o n 初始化之前调用 o r g . s p r i n g f r a m e w o r k . b o o t . d e v t o o l s . a u t o c o n f i g u r e . L o c a l D e v T o o l s A u t o C o n f i g u r a t i o n LiveReloadConfiguration 初始化之前调用 org.springframework.boot.devtools.autoconfigure.LocalDevToolsAutoConfigurationLiveReloadConfiguration初始化之前调用org.springframework.boot.devtools.autoconfigure.LocalDevToolsAutoConfigurationLiveReloadConfiguration 初始化之后调用liveReloadServer 初始化之前调用liveReloadServer 初始化之后调用optionalLiveReloadServer 初始化之前调用2020-08-26 22:13:59.703 INFO 17012 — [ restartedMain] o.s.b.d.a.OptionalLiveReloadServer : LiveReload server is running on port 35729optionalLiveReloadServer 初始化之后调用liveReloadServerEventListener 初始化之前调用liveReloadServerEventListener 初始化之后调用org.springframework.boot.devtools.autoconfigure.LocalDevToolsAutoConfiguration 初始化之前调用org.springframework.boot.devtools.autoconfigure.LocalDevToolsAutoConfiguration 初始化之后调用2020-08-26 22:13:59.729 INFO 17012 — [ restartedMain] c.wno704.boot.BeanLifeCycleApplication : Started BeanLifeCycleApplication in 0.686 seconds (JVM running for 2.332)销毁Menu销毁Dept销毁User可以看到BeanPostProcessor对IOC容器中所有组件都生效。