Spring 5 AbstractBeanFactory -- registerDisposableBeanIfNecessary 源码分析

58 篇文章 1 订阅
56 篇文章 3 订阅

相关源码注释

ApplicationContext

Spring 5 DefaultResourceLoader 源码注释
Spring 5 AbstractApplicationContext 源码注释

BeanFactory

Spring 5 SimpleAliasRegistry 源码注释
Spring 5 DefaultSingletonBeanRegistry 源码注释
Spring 5 FactoryBeanRegistrySupport 源码注释
Spring 5 AbstractBeanFactory 源码注释
Spring 5 AbstractAutowireCapableBeanFactory 源码注释
Spring 5 DefaultLisbaleBeanFactory 源码注释

registerDisposableBeanIfNecessary(beanName, bean, mbd);

将给定Bean添加到该工厂中的可丢弃Bean列表中,注册器可丢弃Bean接口 和/或 在工厂关闭 时调用给定销毁方法(如果适用)。只适用单例

/**
	 * Add the given bean to the list of disposable beans in this factory,
	 * registering its DisposableBean interface and/or the given destroy method
	 * to be called on factory shutdown (if applicable). Only applies to singletons.
	 * <p>将给定Bean添加到该工厂中的可丢弃Bean列表中,注册器可丢弃Bean接口 和/或 在工厂关闭
	 * 时调用给定销毁方法(如果适用)。只适用单例</p>
	 * @param beanName the name of the bean -- bean名
	 * @param bean the bean instance -- bean实例
	 * @param mbd the bean definition for the bean -- bean的BeanDefinition
	 * @see RootBeanDefinition#isSingleton
	 * @see RootBeanDefinition#getDependsOn
	 * @see #registerDisposableBean
	 * @see #registerDependentBean
	 */
	protected void registerDisposableBeanIfNecessary(String beanName, Object bean, RootBeanDefinition mbd) {
		//如果有安全管理器器,获取其访问控制上下文
		AccessControlContext acc = (System.getSecurityManager() != null ? getAccessControlContext() : null);
		//如果 mbd不是Propertype作用域 && bean在关闭时需要销毁
		if (!mbd.isPrototype() && requiresDestruction(bean, mbd)) {
			//如果mbd是单例作用域
			if (mbd.isSingleton()) {
				// Register a DisposableBean implementation that performs all destruction
				// work for the given bean: DestructionAwareBeanPostProcessors,
				// DisposableBean interface, custom destroy method.
				// 注册一个一次性Bean实现来执行给定Bean的销毁工作:DestructionAwareBeanPostProcessors 一次性Bean接口,
				// 自定义销毁方法。
				// DisposableBeanAdapter:实际一次性Bean和可运行接口适配器,对给定Bean实例执行各种销毁步骤
				// 构建Bean对应的DisposableBeanAdapter对象,与beanName绑定到 注册中心的一次性Bean列表中
				registerDisposableBean(beanName,
						new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors(), acc));
			}
			else {
				// A bean with a custom scope...
				// 具有自定已作用域的Bean
				//获取mdb的作用域
				Scope scope = this.scopes.get(mbd.getScope());
				//如果作用域为null
				if (scope == null) {
					//非法状态异常:无作用登记为作用名称'mbd.getScope'
					throw new IllegalStateException("No Scope registered for scope name '" + mbd.getScope() + "'");
				}
				//注册一个回调,在销毁作用域中将构建Bean对应的DisposableBeanAdapter对象指定(或者在销毁整个作用域时执行,
				// 如果作用域没有销毁单个对象,而是全部终止)
				scope.registerDestructionCallback(beanName,
						new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors(), acc));
			}
		}
	}

requiresDestruction(bean, mbd)

确定给定Bean在关闭时是否需要销毁

/**
	 * Determine whether the given bean requires destruction on shutdown.
	 * <p>确定给定Bean在关闭时是否需要销毁</p>
	 * <p>The default implementation checks the DisposableBean interface as well as
	 * a specified destroy method and registered DestructionAwareBeanPostProcessors.
	 * <p>默认实现会检查一次性Bean接口以及指定的销毁方法和注册的 DestructionAwareBeanPostProcessors </p>
	 * @param bean the bean instance to check
	 *             	-- 要检查的Bean实例
	 * @param mbd the corresponding bean definition
	 *            -- 对应的BeanDefinition
	 * @see org.springframework.beans.factory.DisposableBean
	 * @see AbstractBeanDefinition#getDestroyMethodName()
	 * @see org.springframework.beans.factory.config.DestructionAwareBeanPostProcessor
	 */
	protected boolean requiresDestruction(Object bean, RootBeanDefinition mbd) {
		//DestructionAwareBeanPostProcessor :该处理器将在关闭时应用于单例Bean
		// 如果 bean类不是 NullBean && (如果bean有desctory方法 || (该工厂持有一个 DestructionAwareBeanPostProcessor) &&
		// 	Bean有应用于它的可识别销毁的后处理器)) 就为true;否则返回false
		return (bean.getClass() != NullBean.class &&
				(DisposableBeanAdapter.hasDestroyMethod(bean, mbd) || (hasDestructionAwareBeanPostProcessors() &&
						DisposableBeanAdapter.hasApplicableProcessors(bean, getBeanPostProcessors()))));
	}

DisposableBeanAdapter.hasDestroyMethod(bean, mbd)

检查bean是否有desctory方法

  1. 如果bean是DisposableBean实例 || bean 是 AutoClosable实例,返回true
  2. 如果destroyMethodName是’(inferred)’,检查bean是否具有close/shutdown的公共方法,有就返回true
  3. 如果destroyMethodName不是空字符
/**
	 * <p>检查bean是否有desctory方法
	 * </p>
	 * Check whether the given bean has any kind of destroy method to call.
	 * <p>检查给定的Bean是否有任何类型的desctory方法调用</p>
	 * @param bean the bean instance
	 *              -- bean实例
	 * @param beanDefinition the corresponding bean definition
	 *                       -- 对应的BeanDefinition
	 */
	public static boolean hasDestroyMethod(Object bean, RootBeanDefinition beanDefinition) {
		//DisposableBean:要在销毁时释放资源的bean所实现的接口
		//如果bean时DisposableBean实例 || bean 是 AutoClosable实例
		if (bean instanceof DisposableBean || bean instanceof AutoCloseable) {
			//返回true
			return true;
		}
		//获取销毁方法
		String destroyMethodName = beanDefinition.getDestroyMethodName();
		//AbstractBeanDefinition.INFER_METHOD:常量,指示容器应该尝试推断Bean的销毁方法名,而不是显示地指定方法名。
		// 		值'(inferred)'是专门设计 用来在方法名中包含非法字符的,以确保不会与合法命名的同名方法发生冲突。目前,
		// 		在销毁方法推断过程中检测到方法名'close'和'shutdown'(如果存在特点Bean类上的话)
		//如果destroyMethodName是'(inferred)'
		if (AbstractBeanDefinition.INFER_METHOD.equals(destroyMethodName)) {
			// 确定bean类是否具有close/shutdown的公共方法 ,将其结果返回出去
			return (ClassUtils.hasMethod(bean.getClass(), CLOSE_METHOD_NAME) ||
					ClassUtils.hasMethod(bean.getClass(), SHUTDOWN_METHOD_NAME));
		}
		//返回 destroyMethodName是否即不是null又不是长度为0的结果
		return StringUtils.hasLength(destroyMethodName);
	}

hasDestructionAwareBeanPostProcessors()

返回该工厂是否持有一个 DestructionAwareBeanPostProcessor ,该处理器将在关闭时应用于单例Bean
由 AbstractBeanFactory 实现。

/**
	 * Indicates whether any DestructionAwareBeanPostProcessors have been registered.
	 * <p>表明是否注册了任何 destructionawarebeanpostprocessor </p>
	 * */
	private volatile boolean hasDestructionAwareBeanPostProcessors;

/**
	 * Return whether this factory holds a DestructionAwareBeanPostProcessor
	 * that will get applied to singleton beans on shutdown.
	 * <p>返回该工厂是否持有一个 DestructionAwareBeanPostProcessor ,该处理器将在关闭时应用于单例Bean</p>
	 * @see #addBeanPostProcessor
	 * @see org.springframework.beans.factory.config.DestructionAwareBeanPostProcessor
	 */
	protected boolean hasDestructionAwareBeanPostProcessors() {
		return this.hasDestructionAwareBeanPostProcessors;
	}

DisposableBeanAdapter.hasApplicableProcessors(bean, getBeanPostProcessors())

检查给定Bean是否有应用于它的可识别销毁的后处理器

/**
	 * Check whether the given bean has destruction-aware post-processors applying to it.
	 * <p>检查给定Bean是否有应用于它的可识别销毁的后处理器</p>
	 * @param bean the bean instance -- bean实例
	 * @param postProcessors the post-processor candidates -- 候选 post-processor
	 */
	public static boolean hasApplicableProcessors(Object bean, List<BeanPostProcessor> postProcessors) {
		//如果 postProcessors 不是空数组
		if (!CollectionUtils.isEmpty(postProcessors)) {
			//遍历 postProcessors
			for (BeanPostProcessor processor : postProcessors) {
				//如果 processor 是 DestructionAwareBeanPostProcessor 实例
				if (processor instanceof DestructionAwareBeanPostProcessor) {
					DestructionAwareBeanPostProcessor dabpp = (DestructionAwareBeanPostProcessor) processor;
					//确定bean是否需要由dabpp销毁
					if (dabpp.requiresDestruction(bean)) {
						//是就返回true
						return true;
					}
				}
			}
		}
		//默认返回false
		return false;
	}

registerDisposableBean(beanName,disposableBeanAdapter)

将给定Bean添加到注册中心的一次性Bean列表中.
由 AbstractBeanFactory 实现。

/**
	 * Disposable bean instances: bean name to disposable instance.
	 * <p>一次性Bean实例:bean名称 - DisposableBean实例。</p>
	 * */
	private final Map<String, Object> disposableBeans = new LinkedHashMap<>();
	
/**
	 * Add the given bean to the list of disposable beans in this registry.
	 * <p>将给定Bean添加到注册中心的一次性Bean列表中</p>
	 * <p>Disposable beans usually correspond to registered singletons,
	 * matching the bean name but potentially being a different instance
	 * (for example, a DisposableBean adapter for a singleton that does not
	 * naturally implement Spring's DisposableBean interface).
	 * <p>可处置Bean通常与注册的单例相对应,与Bean名称相匹配,但可能是不同的实例(例如,一个单例的可处置Bean适配器,
	 * 该单例不自然地实现Spring的可处理Bean接口)</p>
	 * @param beanName the name of the bean -- bean名
	 * @param bean the bean instance -- bean实例
	 */
	public void registerDisposableBean(String beanName, DisposableBean bean) {
		//使用disposableBeans加锁,保证线程安全
		synchronized (this.disposableBeans) {
			//将beanName,bean添加到disposableBeans中
			this.disposableBeans.put(beanName, bean);
		}
	}

DisposableBeanAdapter

Spring 5 DisposableBeanAdapter 源码注释

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'deptServiceImpl': Unsatisfied dependency expressed through field 'baseMapper'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'deptMapper' defined in file [D:\WorkSpace\work13\djd_server\target\classes\com\jiading\djd\mapper\DeptMapper.class]: Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: org.apache.ibatis.builder.BuilderException: Error creating document instance. Cause: org.xml.sax.SAXParseException; lineNumber: 1; columnNumber: 40; 元素内容必须由格式正确的字符数据或标记组成。 at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:643) ~[spring-beans-5.2.7.RELEASE.jar:5.2.7.RELEASE] at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:130) ~[spring-beans-5.2.7.RELEASE.jar:5.2.7.RELEASE] at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessProperties(AutowiredAnnotationBeanPostProcessor.java:399) ~[spring-beans-5.2.7.RELEASE.jar:5.2.7.RELEASE] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1422) ~[spring-beans-5.2.7.RELEASE.jar:5.2.7.RELEASE] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:594) ~[spring-beans-5.2.7.RELEASE.jar:5.2.7.RELEASE] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:517) ~[spring-beans-5.2.7.RELEASE.jar:5.2.7.RELEASE] at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:323) ~[spring-beans-5.2.7.RELEASE.jar:5.2.7.RELEASE] at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:226) ~[spring-beans-5.2.7.RELEASE.jar:5.2.7.RELEASE] at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:321) ~[spring-beans-5.2.7.RELEASE.jar:5.2.7.RELEASE] at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202) ~[spring-beans-5.2.7.RELEASE.jar:5.2.7.RELEASE] at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:893) ~[spring-beans-5.2.7.RELEASE.jar:5.2.7.RELEASE] at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:879) ~[spring-context-5.2.7.RELEASE.jar:5.2.7.RELEASE] at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:551) ~[spring-context-5.2.7.RELEASE.jar:5.2.7.RELEASE] at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:143) ~[spring-boot-2.3.1.RELEASE.jar:2.3.1.RELEASE] at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:758) [spring-boot-2.3.1.RELEASE.jar:2.3.1.RELEASE] at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:750) [spring-boot-2.3.1.RELEASE.jar:2.3.1.RELEASE] at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:397) [spring-boot-2.3.1.RELEASE.jar:2.3.1.RELEASE] at org.springframework.boot.SpringApplication.run(SpringApplication.java:315) [spring-boot-2.3.1.RELEASE.jar:2.3.1.RELEASE] at org.springframework.boot.SpringApplication.run(SpringApplication.java:1237) [spring-boot-2.3.1.RELEASE.jar:2.3.1.RELEASE] at org.springframework.boot.SpringApplication.run(SpringApplication.java:1226) [spring-boot-2.3.1.RELEASE.jar:2.3.1.RELEASE] at com.jiading.djd.DjdApplication.main(DjdApplication.java:14) [classes/:na]报错了
07-25

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值