关于在Spring 容器 初始化和销毁 bean 前所做的操作有三种方式定义:
-
第一种:通过@PostConstruct 和 @PreDestroy 方法 实现初始化后和销毁bean之前进行的操作
-
第二种:通过bean实现InitializingBean和 DisposableBean接口
-
第三种:通过 在xml中配置init-method 和 destory-method方法,或者 配置@Bean(initMethod = "initMethod", destroyMethod = "destroyMethod") 注解
执行顺序:@PostConstruct -> InitializingBean -> 配置initMethod -> @PreDestroy -> DisposableBean -> 配置destroyMethod
本章介绍第一种
第一种见:【Spring】@PostConstruct 与 @PreDestroy 的实现原理(五)
第二种见:【Spring】InitializingBean与 DisposableBean 接口的实现原理(六)
一、配置initMethod 与 配置destroyMethod 方法
1、BeanPerson类
1 public class BeanPerson { 2 3 public void say(String word) { 4 System.out.println("Hello, " + word); 5 } 6 7 public BeanPerson() { 8 System.out.println("BeanPerson() "); 9 } 10 11 public void initMethod(){ 12 System.out.println("initMethod()...."); 13 } 14 15 public void destroyMethod(){ 16 System.out.println("destroyMethod()...."); 17 } 18 }
2、xml配置
<bean id="person" class="com.test.ioc.BeanPerson" init-method="initMethod" destroy-method="destroyMethod"></bean>
3、@Bean注解配置
@Bean(initMethod = "initMethod", destroyMethod = "destroyMethod")
二、原理图
三、配置initMethod 方法实现原理
1、实例化bean时,createBeat()->doCreateBeat()->initializeBean()
初始化 initializeBean() 方法如下:
1 protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) { 2 if (System.getSecurityManager() != null) { 3 AccessController.doPrivileged((PrivilegedAction<Object>) () -> { 4 invokeAwareMethods(beanName, bean); 5 return null; 6 }, getAccessControlContext()); 7 } else { 8 // 若bean实现了XXXAware接口进行方法的回调 9 invokeAwareMethods(beanName, bean); 10 } 11 12 Object wrappedBean = bean; 13 if (mbd == null || !mbd.isSynthetic()) { 14 // 支持初始化前bean的后置处理器 15 wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName); 16 } 17 18 try { 19 // 调用初始化方法 20 invokeInitMethods(beanName, wrappedBean, mbd); 21 } catch (Throwable ex) { 22 throw new BeanCreationException( 23 (mbd != null ? mbd.getResourceDescription() : null), 24 beanName, "Invocation of init method failed", ex); 25 } 26 if (mbd == null || !mbd.isSynthetic()) { 27 wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName); 28 } 29 30 return wrappedBean; 31 }
2、其中调用了初始化方法 invokeInitMethods() ,如下:
1 protected void invokeInitMethods(String beanName, final Object bean, @Nullable RootBeanDefinition mbd) 2 throws Throwable { 3 // 判断容器中是否实现了InitializingBean接口 4 boolean isInitializingBean = (bean instanceof InitializingBean); 5 if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) { 6 if (logger.isTraceEnabled()) { 7 logger.trace("Invoking afterPropertiesSet() on bean with name '" + beanName + "'"); 8 } 9 if (System.getSecurityManager() != null) { 10 try { 11 AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> { 12 ((InitializingBean) bean).afterPropertiesSet(); 13 return null; 14 }, getAccessControlContext()); 15 } catch (PrivilegedActionException pae) { 16 throw pae.getException(); 17 } 18 } else { 19 // 回调实现InitializingBean接口的afterPropertiesSet()方法 20 ((InitializingBean) bean).afterPropertiesSet(); 21 } 22 } 23 24 if (mbd != null && bean.getClass() != NullBean.class) { 25 // bean定义中看是否有配置的init方法 26 String initMethodName = mbd.getInitMethodName(); 27 // 判断自定义的init方法名称不叫afterPropertiesSet 28 if (StringUtils.hasLength(initMethodName) && 29 !(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) && 30 !mbd.isExternallyManagedInitMethod(initMethodName)) { 31 // 调用配置的初始化方法 32 invokeCustomInitMethod(beanName, bean, mbd); 33 } 34 } 35 }
3、invokeCustomInitMethod() 调用配置的初始化方法
1 protected void invokeCustomInitMethod(String beanName, final Object bean, RootBeanDefinition mbd) 2 throws Throwable { 3 4 // 从bean定义中获取初始化方法名称 5 String initMethodName = mbd.getInitMethodName(); 6 Assert.state(initMethodName != null, "No init method set"); 7 // 获得初始化方法 8 Method initMethod = (mbd.isNonPublicAccessAllowed() ? 9 BeanUtils.findMethod(bean.getClass(), initMethodName) : 10 ClassUtils.getMethodIfAvailable(bean.getClass(), initMethodName)); 11 12 if (initMethod == null) { 13 if (mbd.isEnforceInitMethod()) { 14 throw new BeanDefinitionValidationException("Could not find an init method named '" + 15 initMethodName + "' on bean with name '" + beanName + "'"); 16 } else { 17 if (logger.isTraceEnabled()) { 18 logger.trace("No default init method named '" + initMethodName + 19 "' found on bean with name '" + beanName + "'"); 20 } 21 // Ignore non-existent default lifecycle methods. 22 return; 23 } 24 } 25 26 if (logger.isTraceEnabled()) { 27 logger.trace("Invoking init method '" + initMethodName + "' on bean with name '" + beanName + "'"); 28 } 29 Method methodToInvoke = ClassUtils.getInterfaceMethodIfPossible(initMethod); 30 31 if (System.getSecurityManager() != null) { 32 AccessController.doPrivileged((PrivilegedAction<Object>) () -> { 33 ReflectionUtils.makeAccessible(methodToInvoke); 34 return null; 35 }); 36 try { 37 AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> 38 methodToInvoke.invoke(bean), getAccessControlContext()); 39 } catch (PrivilegedActionException pae) { 40 InvocationTargetException ex = (InvocationTargetException) pae.getException(); 41 throw ex.getTargetException(); 42 } 43 } else { 44 try { 45 ReflectionUtils.makeAccessible(methodToInvoke); 46 // 调用对象的初始化方法 47 methodToInvoke.invoke(bean); 48 } catch (InvocationTargetException ex) { 49 throw ex.getTargetException(); 50 } 51 } 52 }
注:bean定义的初始化方法名称,是在Spring解析的时候,通过判断注解或xml配置的到的,同时解析也会把销毁方法名称,放到bean定义中
四、配置destroyMethod 方法实现原理
1、在容器关闭时,调用方法链:context.clonse() -> doClose() -> destroyBeans() -> destroySingletons() ->destroySingleton()
销毁单例方法 destroySingleton() 如下:
1 public void destroySingleton(String beanName) { 2 // Remove a registered singleton of the given name, if any. 3 // 移除缓存 4 removeSingleton(beanName); 5 6 // Destroy the corresponding DisposableBean instance. 7 DisposableBean disposableBean; 8 // 加锁 9 synchronized (this.disposableBeans) { 10 // 根据名称,从需要销毁的是实例集合移除实例,得到disposableBean 11 disposableBean = (DisposableBean) this.disposableBeans.remove(beanName); 12 } 13 // 销毁bean 14 destroyBean(beanName, disposableBean); 15 }
2、销毁时,从disposableBeans 获取对象(对象是在bean创建的时候,放入的,具体见上一篇)
1 protected void destroyBean(String beanName, @Nullable DisposableBean bean) { 2 // Trigger destruction of dependent beans first... 3 Set<String> dependencies; 4 // 移除依赖 5 synchronized (this.dependentBeanMap) { 6 // Within full synchronization in order to guarantee a disconnected Set 7 dependencies = this.dependentBeanMap.remove(beanName); 8 } 9 if (dependencies != null) { 10 if (logger.isTraceEnabled()) { 11 logger.trace("Retrieved dependent beans for bean '" + beanName + "': " + dependencies); 12 } 13 for (String dependentBeanName : dependencies) { 14 destroySingleton(dependentBeanName); 15 } 16 } 17 18 // Actually destroy the bean now... 19 // 现在真正销毁 20 if (bean != null) { 21 try { 22 // 调用销毁方法 23 bean.destroy(); 24 } 25 catch (Throwable ex) { 26 if (logger.isWarnEnabled()) { 27 logger.warn("Destruction of bean with name '" + beanName + "' threw an exception", ex); 28 } 29 } 30 } 31 32 // Trigger destruction of contained beans... 33 Set<String> containedBeans; 34 synchronized (this.containedBeanMap) { 35 // Within full synchronization in order to guarantee a disconnected Set 36 containedBeans = this.containedBeanMap.remove(beanName); 37 } 38 if (containedBeans != null) { 39 for (String containedBeanName : containedBeans) { 40 destroySingleton(containedBeanName); 41 } 42 } 43 44 // Remove destroyed bean from other beans' dependencies. 45 synchronized (this.dependentBeanMap) { 46 for (Iterator<Map.Entry<String, Set<String>>> it = this.dependentBeanMap.entrySet().iterator(); it.hasNext();) { 47 Map.Entry<String, Set<String>> entry = it.next(); 48 Set<String> dependenciesToClean = entry.getValue(); 49 dependenciesToClean.remove(beanName); 50 if (dependenciesToClean.isEmpty()) { 51 it.remove(); 52 } 53 } 54 } 55 56 // Remove destroyed bean's prepared dependency information. 57 // 移除依赖关系集中对象 58 this.dependenciesForBeanMap.remove(beanName); 59 }
3、bean.destroy() 方法, 这里的bean对象是 DisposableBeanAdapter对象 如下:
1 // 销毁 2 @Override 3 public void destroy() { 4 if (!CollectionUtils.isEmpty(this.beanPostProcessors)) { 5 for (DestructionAwareBeanPostProcessor processor : this.beanPostProcessors) { 6 // 调持销毁前bean的后置处理器 7 processor.postProcessBeforeDestruction(this.bean, this.beanName); 8 } 9 } 10 11 // 判断是否实现DisposableBean接口 12 if (this.invokeDisposableBean) { 13 if (logger.isTraceEnabled()) { 14 logger.trace("Invoking destroy() on bean with name '" + this.beanName + "'"); 15 } 16 try { 17 if (System.getSecurityManager() != null) { 18 AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> { 19 ((DisposableBean) this.bean).destroy(); 20 return null; 21 }, this.acc); 22 } 23 else { 24 // 强转,调用destroy()方法 25 ((DisposableBean) this.bean).destroy(); 26 } 27 } 28 catch (Throwable ex) { 29 String msg = "Invocation of destroy method failed on bean with name '" + this.beanName + "'"; 30 if (logger.isDebugEnabled()) { 31 logger.warn(msg, ex); 32 } 33 else { 34 logger.warn(msg + ": " + ex); 35 } 36 } 37 } 38 39 if (this.destroyMethod != null) { 40 // 调用配置的销毁方法 41 invokeCustomDestroyMethod(this.destroyMethod); 42 } 43 else if (this.destroyMethodName != null) { 44 Method methodToInvoke = determineDestroyMethod(this.destroyMethodName); 45 if (methodToInvoke != null) { 46 // 调用配置的销毁方法 47 invokeCustomDestroyMethod(ClassUtils.getInterfaceMethodIfPossible(methodToInvoke)); 48 } 49 } 50 }
4、其中invokeCustomDestroyMethod() 方法,调用了对象的销毁方法
1 private void invokeCustomDestroyMethod(final Method destroyMethod) { 2 // 销毁方法参数数量 3 int paramCount = destroyMethod.getParameterCount(); 4 final Object[] args = new Object[paramCount]; 5 if (paramCount == 1) { 6 args[0] = Boolean.TRUE; 7 } 8 if (logger.isTraceEnabled()) { 9 logger.trace("Invoking destroy method '" + this.destroyMethodName + 10 "' on bean with name '" + this.beanName + "'"); 11 } 12 try { 13 if (System.getSecurityManager() != null) { 14 AccessController.doPrivileged((PrivilegedAction<Object>) () -> { 15 ReflectionUtils.makeAccessible(destroyMethod); 16 return null; 17 }); 18 try { 19 AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> 20 destroyMethod.invoke(this.bean, args), this.acc); 21 } 22 catch (PrivilegedActionException pax) { 23 throw (InvocationTargetException) pax.getException(); 24 } 25 } 26 else { 27 ReflectionUtils.makeAccessible(destroyMethod); 28 // 调用对象的销毁方法 29 destroyMethod.invoke(this.bean, args); 30 } 31 } 32 catch (InvocationTargetException ex) { 33 String msg = "Destroy method '" + this.destroyMethodName + "' on bean with name '" + 34 this.beanName + "' threw an exception"; 35 if (logger.isDebugEnabled()) { 36 logger.warn(msg, ex.getTargetException()); 37 } 38 else { 39 logger.warn(msg + ": " + ex.getTargetException()); 40 } 41 } 42 catch (Throwable ex) { 43 logger.warn("Failed to invoke destroy method '" + this.destroyMethodName + 44 "' on bean with name '" + this.beanName + "'", ex); 45 } 46 }