Spring bean销毁的过程

一:DefaultSingletonBeanRegistry之destroySingleton(String beanName)
销毁单例bean
	public void destroySingleton(String beanName) {
		// Remove a registered singleton of the given name, if any.
		removeSingleton(beanName);

		// Destroy the corresponding DisposableBean instance.
		DisposableBean disposableBean;
		synchronized (this.disposableBeans) {
			disposableBean = (DisposableBean) this.disposableBeans.remove(beanName);
		}
		destroyBean(beanName, disposableBean);
	}

方法简析:

  • 1.将缓存的单例bean移除出map
  • 2.移除disposableBeans中缓存的DisposableBean对象
  • 3.销毁bean以及依赖于这个单例bean的bean对象,还有单例bean中包含的其他bean
移除缓存的单例bean之removeSingleton(beanName)
	protected void removeSingleton(String beanName) {
		synchronized (this.singletonObjects) {
			this.singletonObjects.remove(beanName);
			this.singletonFactories.remove(beanName);
			this.earlySingletonObjects.remove(beanName);
			this.registeredSingletons.remove(beanName);
		}
	}

方法简析:

  • 1.锁定单例对象缓存map,防止其他线程影响销毁过程
  • 2.从单例对象缓存map中移除bean
  • 3.从单例对象创建工厂map中移除ObjectFactory
  • 4.从earlySingletonObjects中移除bean
  • 5.移除已注册的单例bean的beanName
销毁bean之destroyBean(String beanName, DisposableBean bean)
	protected void destroyBean(String beanName, DisposableBean bean) {
		// Trigger destruction of dependent beans first...
		Set<String> dependencies = this.dependentBeanMap.remove(beanName);
		if (dependencies != null) {
			if (logger.isDebugEnabled()) {
				logger.debug("Retrieved dependent beans for bean '" + beanName + "': " + dependencies);
			}
			for (String dependentBeanName : dependencies) {
				destroySingleton(dependentBeanName);
			}
		}

		// Actually destroy the bean now...
		if (bean != null) {
			try {
				bean.destroy();
			}
			catch (Throwable ex) {
				logger.error("Destroy method on bean with name '" + beanName + "' threw an exception", ex);
			}
		}

		// Trigger destruction of contained beans...
		Set<String> containedBeans = this.containedBeanMap.remove(beanName);
		if (containedBeans != null) {
			for (String containedBeanName : containedBeans) {
				destroySingleton(containedBeanName);
			}
		}

		// Remove destroyed bean from other beans' dependencies.
		synchronized (this.dependentBeanMap) {
			for (Iterator<Map.Entry<String, Set<String>>> it = this.dependentBeanMap.entrySet().iterator(); it.hasNext();) {
				Map.Entry<String, Set<String>> entry = it.next();
				Set<String> dependenciesToClean = entry.getValue();
				dependenciesToClean.remove(beanName);
				if (dependenciesToClean.isEmpty()) {
					it.remove();
				}
			}
		}

		// Remove destroyed bean's prepared dependency information.
		this.dependenciesForBeanMap.remove(beanName);
	}

方法简析:

  • 1.率先销毁所有依赖于这个单例bean的所有bean,道理很简单,如果当前单例bean被销毁了,而依赖于当前单例bean的bean对象调用单例bean时必然会出现空指针异常
  • 2.真正开始执行单例bean的destroy()方法来销毁bean
  • 3.containedBeanMap销毁这个单例bean中包含的其他bean对象(即引入的依赖,但是实际上这个map好像并没有用到,而且引用的bean也不应该立即销毁,因为可能有其他bean同时也在引用,或许应该检查到没有引用的时候再销毁,但是spring中好像并没有这么做)
  • 4.从依赖bean缓存列表dependentBeanMap中(键值对,如service->controller list)删除所有相关被依赖项
  • 5.删除依赖列表dependenciesForBeanMap(键值对,如controller -> service list)
二:DisposableBeanAdapter
上面讲到从disposableBeans列表中移除DisposableBean对象,现在来看一下spring是如何注册DisposableBean对象的:
	public void registerDisposableBean(String beanName, DisposableBean bean) {
		synchronized (this.disposableBeans) {
			this.disposableBeans.put(beanName, bean);
		}
	}

    //AbstractBeanFactory.registerDisposableBeanIfNecessary(String beanName, Object bean, RootBeanDefinition mbd)
	protected void registerDisposableBeanIfNecessary(String beanName, Object bean, RootBeanDefinition mbd) {
		AccessControlContext acc = (System.getSecurityManager() != null ? getAccessControlContext() : null);
		if (!mbd.isPrototype() && requiresDestruction(bean, mbd)) {
			if (mbd.isSingleton()) {
				// Register a DisposableBean implementation that performs all destruction
				// work for the given bean: DestructionAwareBeanPostProcessors,
				// DisposableBean interface, custom destroy method.
				registerDisposableBean(beanName,
						new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors(), acc));
			}
			else {
				// A bean with a custom scope...
				Scope scope = this.scopes.get(mbd.getScope());
				if (scope == null) {
					throw new IllegalStateException("No Scope registered for scope name '" + mbd.getScope() + "'");
				}
				scope.registerDestructionCallback(beanName,
						new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors(), acc));
			}
		}
	}

    //检查是否需要销毁
    //AbstractBeanFactory.requiresDestruction(Object bean, RootBeanDefinition mbd)
	protected boolean requiresDestruction(Object bean, RootBeanDefinition mbd) {
		return (bean != null &&
				(DisposableBeanAdapter.hasDestroyMethod(bean, mbd) || (hasDestructionAwareBeanPostProcessors() &&
						DisposableBeanAdapter.hasApplicableProcessors(bean, getBeanPostProcessors()))));
	}

方法简析:

  • 1.检查当前bean的作用域以及是否需要销毁(比如BeanDefinition是否定义了销毁方法,或者注册了针对该bean的DestructionAwareBeanPostProcessor),多例将不会注册DisposableBean对象
  • 2.如果是单例,则注册DisposableBeanAdapter对象
  • 3.如果不是单例,则有可能是request、session、globalSession、refresh或者其他自定义的scope,这时将会注册异步的销毁对象
DisposableBeanAdapter中重要方法简析
1.构造方法
	public DisposableBeanAdapter(Object bean, String beanName, RootBeanDefinition beanDefinition,
			List<BeanPostProcessor> postProcessors, AccessControlContext acc) {

		Assert.notNull(bean, "Disposable bean must not be null");
		this.bean = bean;
		this.beanName = beanName;
		this.invokeDisposableBean =
				(this.bean instanceof DisposableBean && !beanDefinition.isExternallyManagedDestroyMethod("destroy"));
		this.nonPublicAccessAllowed = beanDefinition.isNonPublicAccessAllowed();
		this.acc = acc;
		String destroyMethodName = inferDestroyMethodIfNecessary(bean, beanDefinition);
		if (destroyMethodName != null && !(this.invokeDisposableBean && "destroy".equals(destroyMethodName)) &&
				!beanDefinition.isExternallyManagedDestroyMethod(destroyMethodName)) {
			this.destroyMethodName = destroyMethodName;
			this.destroyMethod = determineDestroyMethod();
			if (this.destroyMethod == null) {
				if (beanDefinition.isEnforceDestroyMethod()) {
					throw new BeanDefinitionValidationException("Couldn't find a destroy method named '" +
							destroyMethodName + "' on bean with name '" + beanName + "'");
				}
			}
			else {
				Class<?>[] paramTypes = this.destroyMethod.getParameterTypes();
				if (paramTypes.length > 1) {
					throw new BeanDefinitionValidationException("Method '" + destroyMethodName + "' of bean '" +
							beanName + "' has more than one parameter - not supported as destroy method");
				}
				else if (paramTypes.length == 1 && boolean.class != paramTypes[0]) {
					throw new BeanDefinitionValidationException("Method '" + destroyMethodName + "' of bean '" +
							beanName + "' has a non-boolean parameter - not supported as destroy method");
				}
			}
		}
		this.beanPostProcessors = filterPostProcessors(postProcessors, bean);
	}

方法简析:

  • 1.检查是否实现了DisposableBean接口
  • 2.寻找销毁方法名destroyMethodName
  • 3.如果找到了销毁方法,并且bean没有实现DisposableBean接口或者设置了除destroy()之外的方法,以及非外部管理的销毁方法,则会根据destroyMethodName寻找销毁方法(这里需要注意,销毁方法参数不能超过1个,且只能是boolean类型的)
  • 4.在BeanPostProcessor列表中查找实现DestructionAwareBeanPostProcessor接口的实例并且决定当前bean是需要被销毁的,然后将其放入beanPostProcessors列表中
2.寻找销毁方法
	private String inferDestroyMethodIfNecessary(Object bean, RootBeanDefinition beanDefinition) {
		String destroyMethodName = beanDefinition.getDestroyMethodName();
		if (AbstractBeanDefinition.INFER_METHOD.equals(destroyMethodName) ||
				(destroyMethodName == null && closeableInterface.isInstance(bean))) {
			// Only perform destroy method inference or Closeable detection
			// in case of the bean not explicitly implementing DisposableBean
			if (!(bean instanceof DisposableBean)) {
				try {
					return bean.getClass().getMethod(CLOSE_METHOD_NAME).getName();
				}
				catch (NoSuchMethodException ex) {
					try {
						return bean.getClass().getMethod(SHUTDOWN_METHOD_NAME).getName();
					}
					catch (NoSuchMethodException ex2) {
						// no candidate destroy method found
					}
				}
			}
			return null;
		}
		return (StringUtils.hasLength(destroyMethodName) ? destroyMethodName : null);
	}

方法简析:

  • 1.从BeanDefinition中拿到destroyMethodName
  • 2.判断是否是默认值-"(inferred)",或者destroyMethodName为null并且bean是AutoCloseable或Closeable的实现类
  • 3.如果满足上述条件,判断是否是DisposableBean的实现类,如果是则不做推断,如果不是,则尝试获取名"close"或"shutdown"的方法
  • 4.如果不满足条件并且destroyMethodName不为空,则直接返回destroyMethodName
3.bean的销毁行为之destroy()
	public void destroy() {
		if (!CollectionUtils.isEmpty(this.beanPostProcessors)) {
			for (DestructionAwareBeanPostProcessor processor : this.beanPostProcessors) {
				processor.postProcessBeforeDestruction(this.bean, this.beanName);
			}
		}

		if (this.invokeDisposableBean) {
			if (logger.isDebugEnabled()) {
				logger.debug("Invoking destroy() on bean with name '" + this.beanName + "'");
			}
			try {
				if (System.getSecurityManager() != null) {
					AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
						@Override
						public Object run() throws Exception {
							((DisposableBean) bean).destroy();
							return null;
						}
					}, acc);
				}
				else {
					((DisposableBean) bean).destroy();
				}
			}
			catch (Throwable ex) {
				String msg = "Invocation of destroy method failed on bean with name '" + this.beanName + "'";
				if (logger.isDebugEnabled()) {
					logger.warn(msg, ex);
				}
				else {
					logger.warn(msg + ": " + ex);
				}
			}
		}

		if (this.destroyMethod != null) {
			invokeCustomDestroyMethod(this.destroyMethod);
		}
		else if (this.destroyMethodName != null) {
			Method methodToCall = determineDestroyMethod();
			if (methodToCall != null) {
				invokeCustomDestroyMethod(methodToCall);
			}
		}
	}

方法简析:

  • 1.从bean销毁处理器列表beanPostProcessors获取到DestructionAwareBeanPostProcessor实例并执行postProcessBeforeDestruction(Object bean, String beanName)方法进行bean销毁之前的行为
  • 2.如果bean实现了DisposableBean接口,则执行其实现的destroy()行为
  • 3.通过反射执行自定义或推断而出的destroyMethod
  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值