【Spring】配置initMethod 与 配置destroyMethod 的实现原理(七)

  关于在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")

二、原理图

  【Spring】配置initMethod 与 配置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 }

 

上一篇:2021-05-02


下一篇:Spring 之 FactoryBean 的使用和原因