Spring源码(四):注解的收集与依赖注入、initializeBean、Bean的销毁

一、收集注解

        实例化Bean只是在堆内存划了一片空间,Bean中带有@Autowired注解的属性是没有值的。在上一篇提到的doCreateBean里,applyMergedBeanDefinitionPostProcessors中MergedBeanDefinitionPostProcessor的实现类会收集各种注解,有CommonAnnotationBeanPostProcessor、AutowiredAnnotationBeanPostProcessor、等。
在这里插入图片描述

        CommonAnnotationBeanPostProcessor支持@PostConstruct,@PreDestroy,@Resource注解的收集。
        AutowiredAnnotationBeanPostProcessor 支持 @Autowired,@Value注解的收集。
        举例说明@Autowired注解的收集,其他的注解收集与之类似。在AutowiredAnnotationBeanPostProcessor.postProcessMergedBeanDefinition的findAutowiringMetadatametadata = buildAutowiringMetadata(clazz);收集带有@Autowired的字段和方法。先收集到容器里,再把容器和Class封装成InjectionMetadata,放到缓存injectionMetadataCache中后返回。
在这里插入图片描述

二、依赖注入

在这里插入图片描述
        populateBean中支持了@Autowired依赖注入过程。首先看实现了InstantiationAwareBeanPostProcessor接口的调用,在postProcessAfterInstantiation方法中返回false可以让所有类都不能依赖注入。当然,也可以在方法中写逻辑判断,实现部分类依赖注入。
在这里插入图片描述
        接着从这里可以看到依赖注入过程。
在这里插入图片描述
        来到AutowiredAnnotationBeanPostProcessor.postProcessProperties,首先从缓存中拿到InjectionMetadata对象(InjectionMetadata是在applyMergedBeanDefinitionPostProcessors中加入到缓存的)。
在这里插入图片描述
        AutowiredAnnotationBeanPostProcessor.inject的beanFactory.resolveDependency会触发依赖注入属性的getBean操作,这个里面涉及到各种类型的判断,不用深入的去看。
        最后,通过反射完成属性和方法的依赖注入。
在这里插入图片描述
在这里插入图片描述

三、initializeBean

        doCreateBean的initializeBean是实例化和依赖注入完以后的调用。

1. 调用Aware接口

        在invokeAwareMethods中可以看到,这个里面是各种Aware接口的调用。比如说,BeanNameAware.setBeanName可以拿到beanName,BeanFactoryAware.setBeanFactory可以拿到beanFactory对象。
在这里插入图片描述

2. 对类中某些特殊方法的调用,比如@PostConstruct,Aware接口

        来到applyBeanPostProcessorsBeforeInitialization,这里循环调用BeanPostProcessor的postProcessBeforeInitialization方法。下面举一些例子。
        在InitDestroyAnnotationBeanPostProcessor.postProcessBeforeInitialization中看到,可以从缓存中取出带有@PostConstruct的方法,反射调用方法。
在这里插入图片描述
        在ApplicationContextAwareProcessor.postProcessBeforeInitialization中是对EnvironmentAware、ApplicationEventPublisherAware等Aware接口的支撑。
在这里插入图片描述
        在ImportAwareBeanPostProcessor.postProcessBeforeInitialization中可以看到,在ImportAware的实现类的setImportMetadata方法中调用AnnotationMetadata.getAnnotations()能拿到import了这个Bean的类的注解。
在这里插入图片描述
        例如,ImportBean通过@import注解import了AwareBean,如果AwareBean实现了ImportAware接口,就可以在setImportMetadata方法中通过AnnotationMetadata.getAnnotations()拿到ImportBean的所有注解。
在这里插入图片描述
在这里插入图片描述

3. InitializingBean接口、init-method属性调用

        接着来到invokeInitMethods,这里调用了实现InitializingBean接口的afterPropertiesSet方法。
在这里插入图片描述
        下面是对xml中init-method方法的调用。获取init-method属性中的方法,判断方法名称不为afterPropertiesSet,最后反射调用方法。
在这里插入图片描述
        从这里可以看到,带有@PostConstruct的方法、实现InitializingBean接口的afterPropertiesSet方法、init-method配置的方法,这3类方法的作用都是一样的,都是在Bean实例化完成后做一些操作。区别是调用的时序不一样,带有@PostConstruct的方法最开始执行,然后是InitializingBean接口的afterPropertiesSet方法,最后是init-method配置的方法。

4. 另外一些BeanPostProcessor的调用

        从applyBeanPostProcessorsAfterInitialization进入,和applyBeanPostProcessorsBeforeInitialization一样,这里也是循环BeanPostProcessor,调用postProcessAfterInitialization方法。例如,会调用到AbstractAutoProxyCreator类,这是AOP的入口。
在这里插入图片描述
        applyBeanPostProcessorsBeforeInitialization和applyBeanPostProcessorsAfterInitialization都是循环调用BeanPostProcessor。有的BeanPostProcessor在applyBeanPostProcessorsBeforeInitialization对Bean做一些操作,有的BeanPostProcessor在applyBeanPostProcessorsAfterInitialization对Bean做一些操作,这是装饰器设计模式。没有任何操作的就直接返回Bean。

四、Bean销毁前的方法收集与调用

        如果配置了带有@PreDestroy的方法、实现DisposableBean接口的destroy方法、destroy-method方法,在Bean被销毁前就会调用这些方法。
        doCreateBean中建立了beanName与bean销毁时调用的类DisposableBeanAdapter的映射关系。
在这里插入图片描述
        DisposableBeanAdapter的构造方法收集了destroy-method属性中的方法、实现了DisposableBean接口的destroy方法,还收集了@PreDestroy注解的处理类CommonAnnotationBeanPostProcessor。

public DisposableBeanAdapter(Object bean, String beanName, RootBeanDefinition beanDefinition,
			List<BeanPostProcessor> postProcessors, @Nullable 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;
			Method destroyMethod = determineDestroyMethod(destroyMethodName);
			if (destroyMethod == null) {
				if (beanDefinition.isEnforceDestroyMethod()) {
					throw new BeanDefinitionValidationException("Could not find a destroy method named '" +
							destroyMethodName + "' on bean with name '" + beanName + "'");
				}
			}
			else {
				Class<?>[] paramTypes = 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");
				}
				destroyMethod = ClassUtils.getInterfaceMethodIfPossible(destroyMethod);
			}
			this.destroyMethod = destroyMethod;
		}
		this.beanPostProcessors = filterPostProcessors(postProcessors, bean);
	}

        Spring中只能手动调用destroyBean触发Bean销毁前的方法。下图中destroyBean实际上是调用了DisposableBeanAdapter的destroy方法。
在这里插入图片描述
        DisposableBeanAdapter的方法中依次执行了@PreDestroy注解的方法、实现DisposableBean接口的destroy方法、destroy-method属性中的方法。

public void destroy() {
		if (!CollectionUtils.isEmpty(this.beanPostProcessors)) {
			for (DestructionAwareBeanPostProcessor processor : this.beanPostProcessors) {
				processor.postProcessBeforeDestruction(this.bean, this.beanName);
			}
		}

		if (this.invokeDisposableBean) {
			if (logger.isTraceEnabled()) {
				logger.trace("Invoking destroy() on bean with name '" + this.beanName + "'");
			}
			try {
				if (System.getSecurityManager() != null) {
					AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> {
						((DisposableBean) this.bean).destroy();
						return null;
					}, this.acc);
				}
				else {
					((DisposableBean) this.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 methodToInvoke = determineDestroyMethod(this.destroyMethodName);
			if (methodToInvoke != null) {
				invokeCustomDestroyMethod(ClassUtils.getInterfaceMethodIfPossible(methodToInvoke));
			}
		}
	}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值