spring是会把@autowired注解注入的类的所有父类也注入进来。父类不用任何注解就可以被spring容器管理-源码底层告诉你

缘由

学习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中,才会返回。
**最终结论:**spring是会把@autowired、@Resource这些注解注入的类的所有父类也注入进来。父类不用任何注解就可以被spring容器管理。如果子类用service注解了,父类也怼个service注解,当我们将父类用 @Autowired注入任何其他类的时候,就会报错。因为spring容器不知道该用子类引用的那个还是父类这个。这里可以采用@Component(value = “a”)指定父类的名称,然后用 @Resource(name = “a”) private T111111111 t111111111;注入就可以解决。
跟注解继承没关系,注解继承是 父类上的注解必须有被元注解@Inherited注解才行,这个是jdk搞的.

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值