关于在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 的实现原理(五)
一、InitializingBean 和 @DisposableBean 接口使用
1 public class BeanPerson implements InitializingBean, DisposableBean { 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 @Override 12 public void afterPropertiesSet() throws Exception { 13 System.out.println("afterPropertiesSet()......"); 14 } 15 16 @Override 17 public void destroy() throws Exception { 18 System.out.println("destroy()......"); 19 } 20 21 }
二、原理图
实现原理是通过代码逻辑判断bean的类型,是否实现的对应的接口
三、InitializingBean 接口实现原理
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 }
其中,判断类bean是否属于InitializingBean接口,然后调用了afterPropertiesSet()方法
四、DisposableBean 接口实现原理
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、从bean工厂的 disposableBeans 中,获取移除对象,而这个 disposableBeans 销毁对象集合中的对象是从注册的时候来的
查看bean创建逻辑: createBeat()->doCreateBeat(),在 doCreateBeat() 调用了registerDisposableBeanIfNecessary() 方法
1 protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args) 2 throws BeanCreationException { 3 4 // Instantiate the bean. 5 // 实例化的bean会封装成一个BeanWrapper对象 6 // BeanWrapper是对Bean的包装,其接口中所定义的功能很简单包括设置获取被包装的对象,获取被包装bean的属性描述器, 7 // 由于BeanWrapper接口是PropertyAccessor的子接口,因此其也可以设置以及访问被包装对象的属性值。 8 BeanWrapper instanceWrapper = null; 9 if (mbd.isSingleton()) { 10 // 移除工厂bean实例缓存,并获取 11 instanceWrapper = this.factoryBeanInstanceCache.remove(beanName); 12 } 13 if (instanceWrapper == null) { 14 // 使用合适的实例化策略来创建新的实例:工厂方法、构造函数自动注入、简单初始化 该方法很复杂也很重要 15 instanceWrapper = createBeanInstance(beanName, mbd, args); 16 } 17 // 获取包装Bean中的bean实例 18 final Object bean = instanceWrapper.getWrappedInstance(); 19 // 获取包装Bean中的bean的类clazz对象 20 Class<?> beanType = instanceWrapper.getWrappedClass(); 21 if (beanType != NullBean.class) { 22 // 在bean定义中设置类clazz对象类型 23 mbd.resolvedTargetType = beanType; 24 } 25 26 ...... 27 28 // Initialize the bean instance. 29 // 早起暴露的对象 30 Object exposedObject = bean; 31 try { 32 // 给的属性进行赋值(调用set方法进行赋值) 33 populateBean(beanName, mbd, instanceWrapper); 34 // 进行对象初始化操作(在这里可能生成代理对象),调用init方法 35 exposedObject = initializeBean(beanName, exposedObject, mbd); 36 } catch (Throwable ex) { 37 if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) { 38 throw (BeanCreationException) ex; 39 } else { 40 throw new BeanCreationException( 41 mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex); 42 } 43 } 44 45 ...... 46 47 // Register bean as disposable. 48 try { 49 // 注册销毁对象 50 // 将给定Bean添加到该工厂中的可丢弃Bean列表中,注册器可丢弃Bean接口 和/或 51 // 在工厂关闭 时调用给定销毁方法(如果适用)。只适用单例 52 registerDisposableBeanIfNecessary(beanName, bean, mbd); 53 } catch (BeanDefinitionValidationException ex) { 54 throw new BeanCreationException( 55 mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex); 56 } 57 58 return exposedObject; 59 }
3、注册销毁对象方法:registerDisposableBeanIfNecessary()
1 protected void registerDisposableBeanIfNecessary(String beanName, Object bean, RootBeanDefinition mbd) { 2 // 如果有安全管理器器,获取其访问控制上下文 3 AccessControlContext acc = (System.getSecurityManager() != null ? getAccessControlContext() : null); 4 // 判断是否是非多例 && 是否需要在关闭时销毁 5 if (!mbd.isPrototype() && requiresDestruction(bean, mbd)) { 6 if (mbd.isSingleton()) { 7 // Register a DisposableBean implementation that performs all destruction 8 // work for the given bean: DestructionAwareBeanPostProcessors, 9 // DisposableBean interface, custom destroy method. 10 // 注册一个一次性Bean实现来执行给定Bean的销毁工作:DestructionAwareBeanPostProcessors 一次性Bean接口, 11 // 自定义销毁方法。 12 // DisposableBeanAdapter:实际一次性Bean和可运行接口适配器,对给定Bean实例执行各种销毁步骤 13 // 构建Bean对应的DisposableBeanAdapter对象,与beanName绑定到 注册中心的一次性Bean列表中 14 registerDisposableBean(beanName, 15 new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors(), acc)); 16 } 17 else { 18 // A bean with a custom scope... 19 Scope scope = this.scopes.get(mbd.getScope()); 20 if (scope == null) { 21 throw new IllegalStateException("No Scope registered for scope name '" + mbd.getScope() + "'"); 22 } 23 scope.registerDestructionCallback(beanName, 24 new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors(), acc)); 25 } 26 } 27 }
4、其中调用了registerDisposableBean() 方法,并且把原对象和一些其他信息封装成了一个DisposableBeanAdapter对象,放入了工厂的 disposableBeans 集合中
1 // 注册需要销毁的是实例 2 public void registerDisposableBean(String beanName, DisposableBean bean) { 3 synchronized (this.disposableBeans) { 4 this.disposableBeans.put(beanName, bean); 5 } 6 }
5、销毁时,从disposableBeans 获取对象,继续从1步骤的 destroyBean() 方法,往下走
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 }
6、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 }
可以看到其中,判断是否实现DisposableBean接口,然后调用了 ((DisposableBean) this.bean).destroy();
this.bean 即是封装前原实例对象,即调用了原实例对象的 destroy() 方法