初始化与销毁方法中,只避免销毁方法执行两次而初始化方法没有相关的判断
Whale-lyi opened this issue · 1 comments
Whale-lyi commented
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 commented
@Whale-lyi Hi, 感谢你的提醒,有时间可以提个pull request哦