MergedBeanDefinitionPostProcessor和@Autowired,@Value的关系

热爱spring源码的同学应该知道MergedBeanDefinitionPostProcessor这个接口,这个接口对@Autowired和@Value的支持起到了至关重要的作用。当某个bean在实例化的时候就会调到所有的实现了MergedBeanDefinitionPostProcessor接口的实例。其中就有一个非常关键的类:AutowiredAnnotationBeanPostProcessor

1、首先了解一下MergedBeanDefinitionPostProcessor接口实例调用的地方

这个地方就是 MergedBeanDefinitionPostProcessor接口调用的入口,里面会对所有实现了MergedBeanDefinitionPostProcessor接口的bean进行调用,代码如下:

 其中解析扫描类里面的@Autowired和@Value注解的就是AutowiredAnnotationBeanPostProcessor:

让我们重点看一下这个类的源码:

构造函数中把@Autowired和@Value的注解加入到了autowiredAnnotationTypes集合中:

 AutowiredAnnotationBeanPostProcessor类把正在被spring实例化的bean进行@Autowired和@Value扫描,扫描到类里面属性和方法上面如果有注解,就会把对应的方法或者属性封装起来,最终封装成InjectionMetadata对象。

 接着看源码:

扫描clazz的Field上是否有@Autowired和@Value注解,还有一个@Inject,这个很少使用,这里不多说。

 接着看其中的findAutowiredAnnotation方法:

 循环构造函数中添加的@Autowired和@Value容器,看看Field上是否有这两个注解,如果有这两个注解就会处理该Field,否者不处理。

最终会调到这个方法:

 

public static AnnotationAttributes getAnnotationAttributes(Annotation annotation, boolean classValuesAsString,
			boolean nestedAnnotationsAsMap) {

		AnnotationAttributes attrs = new AnnotationAttributes();
		Method[] methods = annotation.annotationType().getDeclaredMethods();
		for (Method method : methods) {
			if (method.getParameterTypes().length == 0 && method.getReturnType() != void.class) {
				try {
					Object value = method.invoke(annotation);
					if (classValuesAsString) {
						if (value instanceof Class) {
							value = ((Class<?>) value).getName();
						}
						else if (value instanceof Class[]) {
							Class<?>[] clazzArray = (Class[]) value;
							String[] newValue = new String[clazzArray.length];
							for (int i = 0; i < clazzArray.length; i++) {
								newValue[i] = clazzArray[i].getName();
							}
							value = newValue;
						}
					}
					if (nestedAnnotationsAsMap && value instanceof Annotation) {
						attrs.put(method.getName(),
							getAnnotationAttributes((Annotation) value, classValuesAsString, nestedAnnotationsAsMap));
					}
					else if (nestedAnnotationsAsMap && value instanceof Annotation[]) {
						Annotation[] realAnnotations = (Annotation[]) value;
						AnnotationAttributes[] mappedAnnotations = new AnnotationAttributes[realAnnotations.length];
						for (int i = 0; i < realAnnotations.length; i++) {
							mappedAnnotations[i] = getAnnotationAttributes(
									realAnnotations[i], classValuesAsString, nestedAnnotationsAsMap);
						}
						attrs.put(method.getName(), mappedAnnotations);
					}
					else {
						attrs.put(method.getName(), value);
					}
				}
				catch (Exception ex) {
					throw new IllegalStateException("Could not obtain annotation attribute values", ex);
				}
			}
		}
		return attrs;
	}

这个方法就是拿到Field上面的@Autowired或者@Value注解,然后获取注解定义中的method,然后反射调用注解定义中的方法拿到注解中定义的属性值。最后一步attrs.put(method.getName(), value); 注解定义中的方法和对应方法的属性值之间建立映射关系。

回到之前代码:

从之前建立的注解属性名和属性值映射关系map中,拿到属性值,然后封装成 AutowiredFieldElement对象,这个对象不要害怕,其实没什么东西。

这个对象继承了InjectionMetadata.InjectedElement,再看看这个InjectionMetadata.InjectedElement

 

这个类其实就是,有一个 member,一个PropertyDescriptor pd,还有一个isField,member是Field和Method的顶层接口,pd是对应的该属性的描述对象,这个是JDK反射包中的内省机制。其实就是把bean中的有@Autowired或者@Value注解的属性或者方法封装成AutowiredFieldElement或者AutowiredMethodElement对象,为后续IOC,依赖注入做准备。

而类中方法的扫描逻辑和属性基本上差不多,这里就不多赘述了,currElements.add(new AutowiredMethodElement(method, required, pd));只是封装的对象不一样。最后把AutowiredFieldElement或者AutowiredMethodElement对象的集合封装成return new InjectionMetadata(clazz, elements);InjectionMetadata对象,这个对象其实就是有类和集合信息而已。

 这样:AutowiredAnnotationBeanPostProcessor类的工作就完成了,让我们总结一下这个类的作用,其实这个类就是在实例化某个bean时,对bean中的属性或者方法进行扫描,扫描的是@Autowired和@Value注解,一旦发现方法或者属性上有这些注解,就把属性或者方法封装成AutowiredFieldElement或者AutowiredMethodElement对象,这个对象有一个Member,属性描述对象PropertyDescriptor,属性描述对象可以对属性进行反射读和写操作。最后把这些对象封装成InjectionMetadata对象,这些对象封装了类Class和集合,集合里面装了AutowiredFieldElement或者AutowiredMethodElement对象。这样AutowiredAnnotationBeanPostProcessor类的装配工作就完成了,在后续IOC,依赖注入,对bean进行依赖注入时就可以根据InjectionMetadata对象里面封装的内容进行属性赋值了。

后续根据InjectionMetadata进行依赖注入的源码,我们在下一篇博客中解读,谢谢大家!!!

 

  • 9
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值