Skip to content

初始化与销毁方法中,只避免销毁方法执行两次而初始化方法没有相关的判断 #63

Description

@Whale-lyi

DisposableBeanAdapter#destroy() 会通过判断避免 bean 继承自 DisposableBean ,且自定方法与 DisposableBean 方法同名导致销毁方法方法执行两次,代码如下

@Override
public void destroy() throws Exception {
    if (bean instanceof DisposableBean) {
	    ((DisposableBean) bean).destroy();
    }

    //避免同时继承自DisposableBean,且自定义方法与DisposableBean方法同名,销毁方法执行两次的情况
    if (StrUtil.isNotEmpty(destroyMethodName) && !(bean instanceof DisposableBean && "destroy".equals(this.destroyMethodName))) {
	    //执行自定义方法
	    Method destroyMethod = ClassUtil.getPublicMethod(bean.getClass(), destroyMethodName);
	    if (destroyMethod == null) {
		    throw new BeansException("Couldn't find a destroy method named '" + destroyMethodName + "' on bean with name '" + beanName + "'");
	    }
	    destroyMethod.invoke(bean);
    }
}

而 AbstractAutowireCapableBeanFactory#invokeInitMethods() 中缺少类似判断,会导致初始化方法执行两次,代码如下

protected void invokeInitMethods(String beanName, Object bean, BeanDefinition beanDefinition) throws Throwable {
    if (bean instanceof InitializingBean) {
	    ((InitializingBean) bean).afterPropertiesSet();
    }
    String initMethodName = beanDefinition.getInitMethodName();
    if (StrUtil.isNotEmpty(initMethodName)) {
	    Method initMethod = ClassUtil.getPublicMethod(beanDefinition.getBeanClass(), initMethodName);
	    if (initMethod == null) {
		    throw new BeansException("Could not find an init method named '" + initMethodName + "' on bean with name '" + beanName + "'");
	    }
	    initMethod.invoke(bean);
    }
}

在查看spring-framework 5.3.x 源码后可以发现源码是做了相关的判断的,如下

protected void invokeInitMethods(String beanName, Object bean, @Nullable RootBeanDefinition mbd)
			throws Throwable {

		boolean isInitializingBean = (bean instanceof InitializingBean);
		if (isInitializingBean && (mbd == null || !mbd.hasAnyExternallyManagedInitMethod("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.hasAnyExternallyManagedInitMethod(initMethodName)) {
				invokeCustomInitMethod(beanName, bean, mbd);
			}
		}
	}

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions