Spring源码分析(二) AutowiredAnnotationBeanPostProcessor

今天药忘吃喽~ 2023-07-19 05:49 42阅读 0赞

https://www.jianshu.com/p/d511bcb502c3

大家用过spring的肯定都用过AutoWired注解,但是你想过自动注入的原理吗,这次就来说下自动注入是怎么实现的。在之前的spring的ioc容器启动过程中,我们都知道,ioc容器的启动是从AbstractApplicationContext的refresh方法开始的,在ioc容器启动时会初始化加载的BeanPostProcessor,那么BeanPostProcessor是什么呢?BeanPostProcessor就是在bean初始化时操作的后置处理器,那么这和自动注入有什么关系呢?这就要从我们要说的AutowiredAnnotationBeanPostProcessor说起了。先来看下AutowiredAnnotationBeanPostProcessor的类的结构

format_png

AutowiredAnnotationBeanPostProcessor

AutowiredAnnotationBeanPostProcessor实现了BeanPostProcessor接口,当 Spring 容器启动时,AutowiredAnnotationBeanPostProcessor 将扫描 Spring 容器中所有 Bean,当发现 Bean 中拥有@Autowired 注解时就找到和其匹配(默认按类型匹配)的 Bean,并注入到对应的地方中去。先来看下buildAutowiringMetadata方法

  1. private InjectionMetadata buildAutowiringMetadata(final Class<?> clazz) {
  2. List<InjectionMetadata.InjectedElement> elements = new ArrayList<>();
  3. Class<?> targetClass = clazz;
  4. do {
  5. final List<InjectionMetadata.InjectedElement> currElements = new ArrayList<>();
  6. ReflectionUtils.doWithLocalFields(targetClass, field -> {
  7. AnnotationAttributes ann = findAutowiredAnnotation(field);
  8. if (ann != null) {
  9. if (Modifier.isStatic(field.getModifiers())) {
  10. if (logger.isInfoEnabled()) {
  11. logger.info("Autowired annotation is not supported on static fields: " + field);
  12. }
  13. return;
  14. }
  15. boolean required = determineRequiredStatus(ann);
  16. currElements.add(new AutowiredFieldElement(field, required));
  17. }
  18. });
  19. ReflectionUtils.doWithLocalMethods(targetClass, method -> {
  20. Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);
  21. if (!BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) {
  22. return;
  23. }
  24. AnnotationAttributes ann = findAutowiredAnnotation(bridgedMethod);
  25. if (ann != null && method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) {
  26. if (Modifier.isStatic(method.getModifiers())) {
  27. if (logger.isInfoEnabled()) {
  28. logger.info("Autowired annotation is not supported on static methods: " + method);
  29. }
  30. return;
  31. }
  32. if (method.getParameterCount() == 0) {
  33. if (logger.isInfoEnabled()) {
  34. logger.info("Autowired annotation should only be used on methods with parameters: " +
  35. method);
  36. }
  37. }
  38. boolean required = determineRequiredStatus(ann);
  39. PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);
  40. currElements.add(new AutowiredMethodElement(method, required, pd));
  41. }
  42. });
  43. elements.addAll(0, currElements);
  44. targetClass = targetClass.getSuperclass();
  45. }
  46. while (targetClass != null && targetClass != Object.class);
  47. return new InjectionMetadata(clazz, elements);
  48. }

buildAutowiringMetadata方法解析等待自动注入类的所有属性。它通过分析所有字段和方法并初始化org.springframework.beans.factory.annotation.InjectionMetadata类的实例来实现。InjectionMetadata类包含要注入的元素的列表。注入是通过Java的 Reflection Field set方法或Method invoke方法完成的。此过程直接在AutowiredAnnotationBeanPostProcessor的方法中调用public void processInjection(Object bean) throws BeanCreationException。它将所有可注入的bean检索为InjectionMetadata实例,并调用它们的inject()方法。

  1. public void inject(Object target, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
  2. Collection<InjectedElement> checkedElements = this.checkedElements;
  3. Collection<InjectedElement> elementsToIterate =
  4. (checkedElements != null ? checkedElements : this.injectedElements);
  5. if (!elementsToIterate.isEmpty()) {
  6. for (InjectedElement element : elementsToIterate) {
  7. if (logger.isTraceEnabled()) {
  8. logger.trace("Processing injected element of bean '" + beanName + "': " + element);
  9. }
  10. element.inject(target, beanName, pvs);
  11. }
  12. }
  13. }

InjectedElement的inject方法

  1. protected void inject(Object target, @Nullable String requestingBeanName, @Nullable PropertyValues pvs)
  2. throws Throwable {
  3. if (this.isField) {
  4. Field field = (Field) this.member;
  5. ReflectionUtils.makeAccessible(field);
  6. field.set(target, getResourceToInject(target, requestingBeanName));
  7. }
  8. else {
  9. if (checkPropertySkipping(pvs)) {
  10. return;
  11. }
  12. try {
  13. Method method = (Method) this.member;
  14. ReflectionUtils.makeAccessible(method);
  15. method.invoke(target, getResourceToInject(target, requestingBeanName));
  16. }
  17. catch (InvocationTargetException ex) {
  18. throw ex.getTargetException();
  19. }
  20. }
  21. }

AutowiredAnnotationBeanPostProcessor类中的另一个重要方法是findAutowiredAnnotation。它通过分析属于一个字段或一个方法的所有注解来查找@Autowired注解。如果未找到@Autowired注解,则返回null,字段或方法也就视为不可注入。

  1. @Nullable
  2. private AnnotationAttributes findAutowiredAnnotation(AccessibleObject ao) {
  3. if (ao.getAnnotations().length > 0) { // autowiring annotations have to be local
  4. for (Class<? extends Annotation> type : this.autowiredAnnotationTypes) {
  5. AnnotationAttributes attributes = AnnotatedElementUtils.getMergedAnnotationAttributes(ao, type);
  6. if (attributes != null) {
  7. return attributes;
  8. }
  9. }
  10. }
  11. return null;
  12. }

至此,spring的自动注入就完成了。
AutowiredAnnotationBeanPostProcessor的分析就到这里了。

作者:skyguard
链接:https://www.jianshu.com/p/d511bcb502c3
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

发表评论

表情:
评论列表 (有 0 条评论,42人围观)

还没有评论,来说两句吧...

相关阅读