Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
Whale-lyi opened this issue Nov 30, 2023 · 1 comment

Comments

@Whale-lyi
Copy link
Contributor

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);
			}
		}
	}
@DerekYRC
Copy link
Owner

@Whale-lyi Hi, 感谢你的提醒,有时间可以提个pull request哦

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants