子类会继承父类的注解吗?-源码底层告诉你

文章目录

    • 缘由
    • 源码
      • 在第三次后置处理器调用时的部分源码:
      • 具体的实现
      • 跟踪 公共的注解后置处理器解析:
      • 或者是AutowiredAnnotationBeanPostProcessor:
      • 那么如何类的注解信息源的?
      • 以AutowiredAnnotationBeanPostProcessor为例:
    • 结论

缘由

学习spring-IOC后置处理器的第三次调用发现一个有意思的点,所以写出来记录一下。

源码

在研究ioc的bean的创建过程,
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean:

在第三次后置处理器调用时的部分源码:

// Allow post-processors to modify the merged bean definition.
		//允许后置处理器修改合并beanDefinition
		synchronized (mbd.postProcessingLock) {
     
			if (!mbd.postProcessed) {
     
				try {
     
					//第三次后置处理器调用
					applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
				}
				catch (Throwable ex) {
     
					throw new BeanCreationException(mbd.getResourceDescription(), beanName,
							"Post-processing of merged bean definition failed", ex);
				}
				mbd.postProcessed = true;
			}
		}

具体的实现

protected void applyMergedBeanDefinitionPostProcessors(RootBeanDefinition mbd, Class<?> beanType, String beanName) {
     
		for (BeanPostProcessor bp : getBeanPostProcessors()) {
     
			if (bp instanceof MergedBeanDefinitionPostProcessor) {
     
				//全部转换成统一格式的BeanPostProcessor的子类MergedBeanDefinitionPostProcessor
				MergedBeanDefinitionPostProcessor bdp = (MergedBeanDefinitionPostProcessor) bp;
				//调用实际的后置处理方法
				bdp.postProcessMergedBeanDefinition(mbd, beanType, beanName);
			}
		}
	}

跟踪 公共的注解后置处理器解析:

public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
     
		//获取类的生命周期的信息,LifecycleMetadata包含初始化方法和销毁方法信息,将获取的类的初始化方法和销毁方法注册
		super.postProcessMergedBeanDefinition(beanDefinition, beanType, beanName);
		//获取类的注解信息源数据
		InjectionMetadata metadata = findResourceMetadata(beanName, beanType, null);
		//注册
		metadata.checkConfigMembers(beanDefinition);
	}

或者是AutowiredAnnotationBeanPostProcessor:

public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
     
		InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null);
		metadata.checkConfigMembers(beanDefinition);
	}

最终都是获取InjectionMetadata 。

那么如何类的注解信息源的?

CommonAnnotationBeanPostProcessor:负责解析@Resource、@WebServiceRef、@EJB三个注解
AutowiredAnnotationBeanPostProcessor:负责@Autowired
AutowiredAnnotationBeanPostProcessor:负责@Persistence

以AutowiredAnnotationBeanPostProcessor为例:

跟踪最终的代码:

	/***
	 * 找到所要注入的类,标记有 @Autowired注解的 field和method 添加到一个list中
	 * 以list和这个class封装成一个InjectionMetadata
	 */
	private InjectionMetadata buildAutowiringMetadata(final Class<?> clazz) {
     
		if (!AnnotationUtils.isCandidateClass(clazz, this.autowiredAnnotationTypes)) {
     
			return InjectionMetadata.EMPTY;
		}

		List<InjectionMetadata.InjectedElement> elements = new ArrayList<>();
		Class<?> targetClass = clazz;

		do {
     
			final List<InjectionMetadata.InjectedElement> currElements = new ArrayList<>();

			ReflectionUtils.doWithLocalFields(targetClass, field -> {
     
				MergedAnnotation<?> ann = findAutowiredAnnotation(field);
				if (ann != null) {
     
					if (Modifier.isStatic(field.getModifiers())) {
     
						if (logger.isInfoEnabled()) {
     
							logger.info("Autowired annotation is not supported on static fields: " + field);
						}
						return;
					}
					boolean required = determineRequiredStatus(ann);
					currElements.add(new AutowiredFieldElement(field, required));
				}
			});

			ReflectionUtils.doWithLocalMethods(targetClass, method -> {
     
				Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);
				if (!BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) {
     
					return;
				}
				MergedAnnotation<?> ann = findAutowiredAnnotation(bridgedMethod);
				if (ann != null && method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) {
     
					if (Modifier.isStatic(method.getModifiers())) {
     
						if (logger.isInfoEnabled()) {
     
							logger.info("Autowired annotation is not supported on static methods: " + method);
						}
						return;
					}
					if (method.getParameterCount() == 0) {
     
						if (logger.isInfoEnabled()) {
     
							logger.info("Autowired annotation should only be used on methods with parameters: " +
									method);
						}
					}
					boolean required = determineRequiredStatus(ann);
					PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);
					currElements.add(new AutowiredMethodElement(method, required, pd));
				}
			});

			elements.addAll(0, currElements);
			targetClass = targetClass.getSuperclass();
		}
		/***
		 * 一直循环封装,直到目标类为null或者父类是Object
		 * -->这里也就说明了如果你在一个子类有@AutoWired注解的 field和method,
		 * 那么会一直扫描父类,直到扫描到Object才停止
		 */
		while (targetClass != null && targetClass != Object.class);
		//封装找到了的method和field,放到InjectionMetadata
		return InjectionMetadata.forElements(elements, clazz);
	}

结论

其他注解对应的后置处理器,我也基本跟了一遍最终都是一样的循环和判断条件。
根据while的条件,可知如果你在一个子类有@AutoWired,@Resource等注解修饰, 那么会一直扫描父类,直到扫描到Object才停止,最后将扫描的该类和该类的所有父类的注解放到list中,才会返回。
**最终结论:**一个类会继承父类的注解。但是目前通过这块源码只找到前面提到的这几种,其他注解没有找到。如果后面研究完ioc,再实验一下。

你可能感兴趣的:(spring,源码学习,spring,java)