热爱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进行依赖注入的源码,我们在下一篇博客中解读,谢谢大家!!!