从接口的名字上不难发现,InitializingBean 的做用就是在 bean 初始化后执行定制化的操做。git
Spring 容器中的 Bean 是有生命周期的,Spring 容许在 Bean 在初始化完成后以及 Bean 销毁前执行特定的操做,经常使用的设定方式有如下三种:spring
注:如下源码分析基于spring 5.0.4
springboot
接口定义以下:ide
public interface InitializingBean { void afterPropertiesSet() throws Exception; }
接口只有一个方法afterPropertiesSet
,此方法的调用入口是负责加载 spring bean 的AbstractAutowireCapableBeanFactory
,源码以下:spring-boot
protected void invokeInitMethods(String beanName, final Object bean, @Nullable RootBeanDefinition mbd) throws Throwable { boolean isInitializingBean = (bean instanceof InitializingBean); if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) { if (logger.isDebugEnabled()) { logger.debug("Invoking afterPropertiesSet() on bean with name '" + beanName + "'"); } if (System.getSecurityManager() != null) { try { AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> { ((InitializingBean) bean).afterPropertiesSet(); return null; }, getAccessControlContext()); } catch (PrivilegedActionException pae) { throw pae.getException(); } } else { ((InitializingBean) bean).afterPropertiesSet(); } }
从这段源码能够得出如下结论:源码分析
经过 debug 和调用栈找到类InitDestroyAnnotationBeanPostProcessor
, 其中的核心方法,即 @PostConstruct
方法调用的入口:post
@Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { LifecycleMetadata metadata = findLifecycleMetadata(bean.getClass()); try { metadata.invokeInitMethods(bean, beanName); } catch (InvocationTargetException ex) { throw new BeanCreationException(beanName, "Invocation of init method failed", ex.getTargetException()); } catch (Throwable ex) { throw new BeanCreationException(beanName, "Failed to invoke init method", ex); } return bean; }
从命名上,咱们就能够获得某些信息——这是一个BeanPostProcessor。想到了什么?在也谈Spring容器的生命周期中,提到过BeanPostProcessor的postProcessBeforeInitialization是在Bean生命周期中afterPropertiesSet和init-method以前被调用的。另外经过跟踪,@PostConstruct
方法的调用方式也是经过发射机制。debug
@PostConstruct
注解的方法 --> afterPropertiesSet
方法 --> init-method
指定的方法。具体能够参考例子afterPropertiesSet
经过接口实现方式调用(效率上高一点),@PostConstruct
和init-method
都是经过反射机制调用直接执行单测com.skyarthur.springboot.common.bean.InitSequenceBeanTest
, 请戳代码下载地址code
核心代码以下:blog
@Slf4j public class InitSequenceBean implements InitializingBean { public InitSequenceBean() { log.info("InitSequenceBean: construct"); } @Override public void afterPropertiesSet() throws Exception { log.info("InitSequenceBean: afterPropertiesSet"); } @PostConstruct public void postConstruct() { log.info("InitSequenceBean: postConstruct"); } public void initMethod() { log.info("InitSequenceBean: initMethod"); } } @Configuration public class SystemConfig { @Bean(initMethod = "initMethod", name = "initSequenceBean") public InitSequenceBean initSequenceBean() { return new InitSequenceBean(); } } @Slf4j public class InitSequenceBeanTest extends ApplicationTests { @Autowired private InitSequenceBean initSequenceBean; @Test public void initSequenceBeanTest() { log.info("Finish: {}", initSequenceBean.toString()); } }