这里介绍在SpringBoot Bean生命周期当中常用的Hook
Bean实例化时的Hook
Spring Boot Bean在实例化时常用的Hook有:
- @PostConstruct注解
- InitializingBean接口的afterPropertiesSet方法
- @Bean注解的initMethod属性
调用顺序依次为:@PostConstruct注解标记的方法 -> InitializingBean接口的afterPropertiesSet方法 -> @Bean注解中initMethod属性指定的方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| import org.springframework.beans.factory.InitializingBean; import javax.annotation.PostConstruct; import lombok.extern.slf4j.Slf4j;
@Slf4j public class Dog implements InitializingBean { public void hello() { log.info("call by hook: @PostConstruct"); }
@Override public void afterPropertiesSet() throws Exception { log.info("call by hook: afterPropertiesSet of InitializingBean"); }
public void hi() { log.info("call by hook: initMethod of @Bean"); } }
|
1 2 3 4 5 6 7 8 9 10 11
| import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration;
@Configuration public class DogConfig {
@Bean(initMethod = "hi") public Dog dog() { return new Dog(); } }
|
特别地,BeanPostProcessor接口则可用于拦截所有Bean的实例化。具体地:
- postProcessBeforeInitialization方法:该方法会在调用Bean的初始化方法之前被调用
- postProcessAfterInitialization方法:该方法会在调用Bean的初始化方法之后被调用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| import lombok.extern.slf4j.Slf4j; import org.springframework.beans.BeansException; import org.springframework.beans.factory.config.BeanPostProcessor; import org.springframework.stereotype.Component;
@Component @Slf4j public class MyCustomBeanPostProcessor implements BeanPostProcessor { @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { log.info("exec before method, bean name: {}", beanName); return BeanPostProcessor.super.postProcessBeforeInitialization(bean, beanName); }
@Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { log.info("exec after method, bean name {}", beanName); return BeanPostProcessor.super.postProcessAfterInitialization(bean, beanName); } }
|
Bean销毁时的Hook
Spring Boot Bean在销毁时常用的Hook有:
- @PreDestroy注解
- DisposableBean接口的destroy方法
- @Bean注解的destroyMethod属性
调用顺序依次为:@PreDestroy注解注解标记的方法 -> DisposableBean接口的destroy方法 -> @Bean注解中destroyMethod属性指定的方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.DisposableBean; import javax.annotation.PreDestroy;
@Slf4j public class Male implements DisposableBean {
@PreDestroy public void gg() { log.info("call by hook: @PreDestroy"); }
@Override public void destroy() throws Exception { log.info("call by hook: destroy of DisposableBean"); }
public void bye() { log.info("call by hook: destroyMethod of @Bean"); }
}
|
1 2 3 4 5 6 7 8 9 10 11 12
| import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration;
@Configuration public class MaleConfig {
@Bean(destroyMethod = "bye") public Male male() { return new Male(); }
}
|
Note: 利用@Bean注解创建实例时需要注意,@Bean注解存在 销毁方法推断 的行为。即如果没有显式设置destroyMethod属性时,其会将public公共的、无参的、命名为close或shutdown的方法 自动注册为该Bean的销毁方法。如果需要禁用某个@Bean注解的 销毁方法推断 行为,可以将destroyMethod属性显式设置为””空字符串