Spring中有三种初始化Bean的方式:
- 对初始化方法添加注解 @PostConstruct
- 实现 InitializingBean 接口
- 实现 SmartInitializingSingleton 接口
首先要测试三种初始化的执行顺序,如下代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| @Component public class InitTest implements InitializingBean, SmartInitializingSingleton {
@PostConstruct public void postConstruct() { System.out.println("@PostConstruct"); }
@Override public void afterPropertiesSet() throws Exception { System.out.println("afterPropertiesSet"); }
@Override public void afterSingletonsInstantiated() { System.out.println("afterSingletonsInstantiated"); } }
|
执行顺序显而易见,接下开是要说下这三种方式都是在什么地方进行执行的。
初始化 bean 的部分代码在 AbstractAutowireCapableBeanFactory.java
中的 initializeBean
方法中。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
| protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) { if (System.getSecurityManager() != null) { AccessController.doPrivileged((PrivilegedAction<Object>) () -> { invokeAwareMethods(beanName, bean); return null; }, getAccessControlContext()); } else { invokeAwareMethods(beanName, bean); }
Object wrappedBean = bean; if (mbd == null || !mbd.isSynthetic()) { wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName); }
try { invokeInitMethods(beanName, wrappedBean, mbd); } catch (Throwable ex) { throw new BeanCreationException( (mbd != null ? mbd.getResourceDescription() : null), beanName, "Invocation of init method failed", ex); } if (mbd == null || !mbd.isSynthetic()) { wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName); }
return wrappedBean; }
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName) throws BeansException {
Object result = existingBean; for (BeanPostProcessor processor : getBeanPostProcessors()) { Object current = processor.postProcessBeforeInitialization(result, beanName); if (current == null) { return result; } result = current; } return result; }
|
@PostConstruct
① 那个位置上,会取出所有的 BeanPostProcessor 接口,并依次调用,其中有个后处理器为 CommonAnnotationBeanPostProcessor
,它就是处理 PostConstruct 的关键,它的构造方法中 含有 PostConstruct 注解,声明拥有这个注解的方法是初始化方法。
1 2 3 4 5 6
| public CommonAnnotationBeanPostProcessor() { setOrder(Ordered.LOWEST_PRECEDENCE - 3); setInitAnnotationType(PostConstruct.class); setDestroyAnnotationType(PreDestroy.class); ignoreResourceType("javax.xml.ws.WebServiceContext"); }
|
它还继承了 InitDestroyAnnotationBeanPostProcessor
,该父类实现了 BeanPostProcessor 的接口,它本身未实现。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { // metadata 中包是含有 PostConstruct 注解的方法,具体寻找过程不作说明 InitDestroyAnnotationBeanPostProcessor.LifecycleMetadata metadata = findLifecycleMetadata(bean.getClass()); try { // 调用含有 PostConstruct 注解的方法 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; }
|
InitializingBean
② 这个位置上会调用 bean 的 InitializingBean 方法,这个方法会判断这个 bean 是否实现了 InitializingBean 接口,如果实现了,则调用其 afterPropertiesSet() 方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| 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.isTraceEnabled()) { logger.trace("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(); } }
if (mbd != null && bean.getClass() != NullBean.class) { String initMethodName = mbd.getInitMethodName(); if (StringUtils.hasLength(initMethodName) && !(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) && !mbd.isExternallyManagedInitMethod(initMethodName)) { invokeCustomInitMethod(beanName, bean, mbd); } } }
|
SmartInitializingSingleton