1.spring官方指定了三种初始化回调方法
1.1、@PostConstruct、@PreDestory
1.2、实现 InitializingBean DisposableBean 接口
1.3、设置init-method和destory-method
三种方式的优先级从高到低
在spring官方文档里面有明确指出
1 Multiple lifecycle mechanisms configured for the same bean, with 2 different initialization methods, are called as follows: 3 Methods annotated with @PostConstruct 4 afterPropertiesSet() as defined by the InitializingBean callback interface 5 A custom configured init() method 6 Destroy methods are called in the same order: 7 Methods annotated with @PreDestroy 8 destroy() as defined by the DisposableBean callback interface 9 A custom configured destroy() method
2.三种配置初始化bean的方式,调用时机不同,对于注解,是在spring生命周期中第七个bean后置处理器调用的时候,由CommonAnnotationBeanPostProcessor的postProcessBeforeInitialization()方法来处理
而剩下的两种是在 第七个bean后置处理器执行之后的下一行代码中执行的
3.@PostConstruct和@PreDestroy源码
3.1、在spring生命周期中,第三个后置处理器方法:org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#applyMergedBeanDefinitionPostProcessors;在CommonAnnotationBeanPostProcessor的postProcessMergedBeanDefinition方法,调用了buildLifecycleMetadata()方法,有一段比较重要的代码:
1 do { 2 final List<LifecycleElement> currInitMethods = new ArrayList<>(); 3 final List<LifecycleElement> currDestroyMethods = new ArrayList<>(); 4 5 ReflectionUtils.doWithLocalMethods(targetClass, method -> { 6 //如果目标类中的方法,添加了@PostConstruct注解,就添加到currInitMethods 7 if (this.initAnnotationType != null && method.isAnnotationPresent(this.initAnnotationType)) { 8 LifecycleElement element = new LifecycleElement(method); 9 currInitMethods.add(element); 10 if (logger.isTraceEnabled()) { 11 logger.trace("Found init method on class [" + clazz.getName() + "]: " + method); 12 } 13 } 14 //如果目标类的方法,添加了@PreDestory注解,就添加到currDestroyMethod中 15 if (this.destroyAnnotationType != null && method.isAnnotationPresent(this.destroyAnnotationType)) { 16 currDestroyMethods.add(new LifecycleElement(method)); 17 if (logger.isTraceEnabled()) { 18 logger.trace("Found destroy method on class [" + clazz.getName() + "]: " + method); 19 } 20 } 21 }); 22 23 initMethods.addAll(0, currInitMethods); 24 destroyMethods.addAll(currDestroyMethods); 25 targetClass = targetClass.getSuperclass(); 26 } 27 while (targetClass != null && targetClass != Object.class);
这里,最终会根据initMethods和destroyMethods来初始化一个LifecycleMetadata对象,然后再把new出来的元对象,存到了一个map中 lifecycleMetadataCache
1 private LifecycleMetadata findLifecycleMetadata(Class<?> clazz) { 2 if (this.lifecycleMetadataCache == null) { 3 // Happens after deserialization, during destruction... 4 return buildLifecycleMetadata(clazz); 5 } 6 // Quick check on the concurrent map first, with minimal locking. 7 LifecycleMetadata metadata = this.lifecycleMetadataCache.get(clazz); 8 if (metadata == null) { 9 synchronized (this.lifecycleMetadataCache) { 10 metadata = this.lifecycleMetadataCache.get(clazz); 11 if (metadata == null) { 12 metadata = buildLifecycleMetadata(clazz); 13 this.lifecycleMetadataCache.put(clazz, metadata); 14 } 15 return metadata; 16 } 17 } 18 return metadata; 19 }
3.2、在spring生命周期的第七个后置处理器方法中,org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor#postProcessBeforeInitialization
会尝试先从lifecycleMetadataCache中根据class,获取到元对象,然后调用元对象的 invokeInitMethods()方法
1 public void invokeInitMethods(Object target, String beanName) throws Throwable { 2 Collection<LifecycleElement> checkedInitMethods = this.checkedInitMethods; 3 Collection<LifecycleElement> initMethodsToIterate = 4 (checkedInitMethods != null ? checkedInitMethods : this.initMethods); 5 if (!initMethodsToIterate.isEmpty()) { 6 boolean debug = logger.isDebugEnabled(); 7 for (LifecycleElement element : initMethodsToIterate) { 8 if (debug) { 9 logger.debug("Invoking init method on bean '" + beanName + "': " + element.getMethod()); 10 } 11 element.invoke(target); 12 } 13 } 14 }
这里的element.invoke()就是调用bean中添加了@PostConstruct注解的方法(method.invoke())
@PreDestory注解的原理是一样的,只是调用时机是在调用annotationConfigApplicationContext.close()方法的时候,会调用
org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor#postProcessBeforeDestruction
4.剩下的两种初始化方法,执行处理逻辑,是在一块代码中
//在调用第七个后置处理器的下一行,是这个代码
try {
invokeInitMethods(beanName, wrappedBean, mbd);
}
1 protected void invokeInitMethods(String beanName, final Object bean, @Nullable RootBeanDefinition mbd) 2 throws Throwable { 3 4 //判断当前bean是否是 InitializingBean接口的实现类,如果是,判断是否实现了 afterPropertiesSet() 方法 5 boolean isInitializingBean = (bean instanceof InitializingBean); 6 if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) { 7 if (logger.isTraceEnabled()) { 8 logger.trace("Invoking afterPropertiesSet() on bean with name '" + beanName + "'"); 9 } 10 if (System.getSecurityManager() != null) { 11 try { 12 AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> { 13 ((InitializingBean) bean).afterPropertiesSet(); 14 return null; 15 }, getAccessControlContext()); 16 } 17 catch (PrivilegedActionException pae) { 18 throw pae.getException(); 19 } 20 } 21 else { 22 ((InitializingBean) bean).afterPropertiesSet(); 23 } 24 } 25 26 //如果是在@Bean中配置了init-method和destroy-method,那执行的是这里的方法 27 if (mbd != null && bean.getClass() != NullBean.class) { 28 String initMethodName = mbd.getInitMethodName(); 29 if (StringUtils.hasLength(initMethodName) && 30 !(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) && 31 !mbd.isExternallyManagedInitMethod(initMethodName)) { 32 invokeCustomInitMethod(beanName, bean, mbd); 33 } 34 } 35 }
对于在@Bean注解指定init-method方式的,是在将class扫描到beanDefinition的时候,会对@Bean这种方式的bean进行处理
loadBeanDefinitionsForBeanMethod(beanMethod);在这里会设置bean的initMethod
spring扫描bean,将class扫描到beanDefinitionMap中有三种方式;
@ComponentScan注解
@Import
importBeanDefinitionRegistrar
importSelector
@Bean
5.对于销毁方法,还没仔细研究,后面了解之后,再做补充:
1 public void destroy() { 2 //这里是处理@PreDestroy注解的销毁方法 3 if (!CollectionUtils.isEmpty(this.beanPostProcessors)) { 4 for (DestructionAwareBeanPostProcessor processor : this.beanPostProcessors) { 5 processor.postProcessBeforeDestruction(this.bean, this.beanName); 6 } 7 } 8 9 if (this.invokeDisposableBean) { 10 if (logger.isTraceEnabled()) { 11 logger.trace("Invoking destroy() on bean with name '" + this.beanName + "'"); 12 } 13 try { 14 if (System.getSecurityManager() != null) { 15 AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> { 16 ((DisposableBean) this.bean).destroy(); 17 return null; 18 }, this.acc); 19 } 20 else { 21 //这里是处理 DisposableBean 接口实现类中destroy()销毁方法的逻辑 22 ((DisposableBean) this.bean).destroy(); 23 } 24 } 25 catch (Throwable ex) { 26 String msg = "Invocation of destroy method failed on bean with name '" + this.beanName + "'"; 27 if (logger.isDebugEnabled()) { 28 logger.warn(msg, ex); 29 } 30 else { 31 logger.warn(msg + ": " + ex); 32 } 33 } 34 } 35 36 //这是处理@Bean中 destory-method这种方式的销毁方法 37 if (this.destroyMethod != null) { 38 invokeCustomDestroyMethod(this.destroyMethod); 39 } 40 else if (this.destroyMethodName != null) { 41 Method methodToInvoke = determineDestroyMethod(this.destroyMethodName); 42 if (methodToInvoke != null) { 43 invokeCustomDestroyMethod(ClassUtils.getInterfaceMethodIfPossible(methodToInvoke)); 44 } 45 } 46 }