DerekYRC / mini-spring

mini-spring是简化版的spring框架,能帮助你快速熟悉spring源码和掌握spring的核心原理。抽取了spring的核心逻辑,代码极度简化,保留spring的核心功能,如IoC和AOP、资源加载器、事件监听器、类型转换、容器扩展点、bean生命周期和作用域、应用上下文等核心功能。

Home Page:https://github.com/DerekYRC/mini-spring

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

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

Whale-lyi opened this issue · comments

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);
			}
		}
	}

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