Springboot启动过程中的这个BeanPostProcessor,你知道干什么的吗

时间:2021-08-03 00:58:21

Springboot启动过程中的这个BeanPostProcessor,你知道干什么的吗

环境:Springboot2.3.12RELEASE

主要内容:

MergedBeanDefinitionPostProcessor处理器的作用

MergedBeanDefinitionPostProcessor合并Bean定义处理器,该处理器有什么用处?通过源码来查看具体的功能

这里从创建一个Bean实例开始说起。

1 环境准备

  1. @Component 
  2. public class PersonDAOImpl implements PersonDAO { 
  3.  
  4.     @Override 
  5.     public void save() { 
  6.         System.out.println("保存Person信息") ; 
  7.     } 
  8.  
  9. @Service 
  10. public class UsersService { 
  11.      
  12.     @Autowired 
  13.     private PersonDAO personDAO ; 
  14.      
  15.     public void saveUsers(Users users) { 
  16.         System.out.println("保存用户信息") ; 
  17.     } 
  18.      

2 创建实例

  1. public abstract class AbstractAutowireCapableBeanFactory { 
  2.     protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) { 
  3.         BeanWrapper instanceWrapper = null
  4.         if (instanceWrapper == null) { 
  5.             instanceWrapper = createBeanInstance(beanName, mbd, args); 
  6.         } 
  7.         // Allow post-processors to modify the merged bean definition. 
  8.         synchronized (mbd.postProcessingLock) { 
  9.             if (!mbd.postProcessed) { 
  10.                 try { 
  11.                     // 在创建实例后调用MergedBeanDefinitionPostProcessor的postProcessMergedBeanDefinition方法 
  12.                     applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName); 
  13.                 } catch (Throwable ex) { 
  14.                 } 
  15.                 mbd.postProcessed = true
  16.             } 
  17.         } 
  18.     } 

3 执行合并Bean定义方法

  1. public abstract class AbstractAutowireCapableBeanFactory { 
  2.     protected void applyMergedBeanDefinitionPostProcessors(RootBeanDefinition mbd, Class<?> beanType, String beanName) { 
  3.         for (BeanPostProcessor bp : getBeanPostProcessors()) { 
  4.             if (bp instanceof MergedBeanDefinitionPostProcessor) { 
  5.                 MergedBeanDefinitionPostProcessor bdp = (MergedBeanDefinitionPostProcessor) bp; 
  6.                 bdp.postProcessMergedBeanDefinition(mbd, beanType, beanName); 
  7.             } 
  8.         } 
  9.     } 

在这里符合要求的BeanPostProcessor对象有:

CommonAnnotationBeanPostProcessor和AutowiredAnnotationBeanPostProcessor(这里值列出重点的两个)Common这个主要处理:@PostConstruct和@PreDestroy及@Resource等相关的注解;Autowired主要处理的是:@Autowired和@Value及@Inject注解

上面的准备的类中在UserService中通过@Autowired注入了PersonDAO对象,所以这里我们主要是看下

AutowiredAnnotationBeanPostProcessor处理器。

4 处理执行

  1. public class AutowiredAnnotationBeanPostProcessor { 
  2.     private final Map<String, InjectionMetadata> injectionMetadataCache = new ConcurrentHashMap<>(256); 
  3.     private final Set<Class<? extends Annotation>> autowiredAnnotationTypes = new LinkedHashSet<>(4); 
  4.      
  5.     public AutowiredAnnotationBeanPostProcessor() { 
  6.         this.autowiredAnnotationTypes.add(Autowired.class); 
  7.         this.autowiredAnnotationTypes.add(Value.class); 
  8.         try { 
  9.             this.autowiredAnnotationTypes.add((Class<? extends Annotation>) 
  10.                     ClassUtils.forName("javax.inject.Inject", AutowiredAnnotationBeanPostProcessor.class.getClassLoader())); 
  11.             logger.trace("JSR-330 'javax.inject.Inject' annotation found and supported for autowiring"); 
  12.         } 
  13.         catch (ClassNotFoundException ex) { 
  14.             // JSR-330 API not available - simply skip. 
  15.         } 
  16.     } 
  17.      
  18.     public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) { 
  19.         // 查找 
  20.         InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null); 
  21.         metadata.checkConfigMembers(beanDefinition); 
  22.     } 
  23.     private InjectionMetadata findAutowiringMetadata(String beanName, Class<?> clazz, @Nullable PropertyValues pvs) { 
  24.         // Fall back to class name as cache keyfor backwards compatibility with custom callers. 
  25.         // 生成缓存使用的Key名称,后续会通过该Key将对应的信息缓存起来 
  26.         String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName()); 
  27.         // 从当前的缓存中获取是否存在 
  28.         InjectionMetadata metadata = this.injectionMetadataCache.get(cacheKey); 
  29.         // 该方法中会判断缓存中是否存在,上面的metadata;以下通过双重检查 
  30.         if (InjectionMetadata.needsRefresh(metadata, clazz)) { 
  31.             synchronized (this.injectionMetadataCache) { 
  32.                 metadata = this.injectionMetadataCache.get(cacheKey); 
  33.                 if (InjectionMetadata.needsRefresh(metadata, clazz)) { 
  34.                     if (metadata != null) { 
  35.                         metadata.clear(pvs); 
  36.                     } 
  37.                     // 构建自动装配元信息;通过当前在这处理的class对象查找是否具有@Autowired注解信息(从字段和方法上查找) 
  38.                     metadata = buildAutowiringMetadata(clazz); 
  39.                     // 将查找到的InjectionMetadata缓存起来,在后续填充属性的时候直接通过缓存获取即可 
  40.                     this.injectionMetadataCache.put(cacheKey, metadata); 
  41.                 } 
  42.             } 
  43.         } 
  44.         return metadata; 
  45.     } 
  46.      
  47.     private InjectionMetadata buildAutowiringMetadata(final Class<?> clazz) { 
  48.         if (!AnnotationUtils.isCandidateClass(clazz, this.autowiredAnnotationTypes)) { 
  49.             return InjectionMetadata.EMPTY; 
  50.         } 
  51.         List<InjectionMetadata.InjectedElement> elements = new ArrayList<>(); 
  52.         Class<?> targetClass = clazz; 
  53.  
  54.         do { 
  55.             final List<InjectionMetadata.InjectedElement> currElements = new ArrayList<>(); 
  56.             // 这里通过方法也能知道遍历当前类中的所有字段,检查是否有@Autowired注解 
  57.             ReflectionUtils.doWithLocalFields(targetClass, field -> { 
  58.                 // 在字段上查找@Autowired注解信息 
  59.                 MergedAnnotation<?> ann = findAutowiredAnnotation(field); 
  60.                 if (ann != null) { 
  61.                     // 判断当前的字段是否通过static修饰了 
  62.                     if (Modifier.isStatic(field.getModifiers())) { 
  63.                         return
  64.                     } 
  65.                     // 判断是否必须的字段(默认是true,要注入的Bean必须存在) 
  66.                     boolean required = determineRequiredStatus(ann); 
  67.                     // 将查找到的字段信息保存到AutowriedFieldElement中 
  68.                     currElements.add(new AutowiredFieldElement(field, required)); 
  69.                 } 
  70.             }); 
  71.             // 遍历当前class中所有的方法,是否有@Autowired注解信息 
  72.             ReflectionUtils.doWithLocalMethods(targetClass, method -> { 
  73.                 Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method); 
  74.                 if (!BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) { 
  75.                     return
  76.                 } 
  77.                 MergedAnnotation<?> ann = findAutowiredAnnotation(bridgedMethod); 
  78.                 if (ann != null && method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) { 
  79.                     if (Modifier.isStatic(method.getModifiers())) { 
  80.                         return
  81.                     } 
  82.                     boolean required = determineRequiredStatus(ann); 
  83.                     PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz); 
  84.                     currElements.add(new AutowiredMethodElement(method, required, pd)); 
  85.                 } 
  86.             }); 
  87.             elements.addAll(0, currElements); 
  88.             targetClass = targetClass.getSuperclass(); 
  89.         // 遍历当前的类及父类,一直找到父类为Object为止 
  90.         } while (targetClass != null && targetClass != Object.class); 
  91.         return InjectionMetadata.forElements(elements, clazz); 
  92.     } 
  93.     @Nullable 
  94.     private MergedAnnotation<?> findAutowiredAnnotation(AccessibleObject ao) { 
  95.         MergedAnnotations annotations = MergedAnnotations.from(ao); 
  96.         // 开始遍历当前的字段(方法)上是否有autowiredAnnotationTypes集合中定义的注解(该集合在构造该对象的时候就添加了) 
  97.         for (Class<? extends Annotation> type : this.autowiredAnnotationTypes) { 
  98.             MergedAnnotation<?> annotation = annotations.get(type); 
  99.             if (annotation.isPresent()) { 
  100.                 return annotation; 
  101.             } 
  102.         } 
  103.         return null
  104.     } 
  105.  
  106. public abstract class ReflectionUtils { 
  107.     public static void doWithLocalFields(Class<?> clazz, FieldCallback fc) { 
  108.         for (Field field : getDeclaredFields(clazz)) { 
  109.             try { 
  110.                 fc.doWith(field); 
  111.             } catch (IllegalAccessException ex) { 
  112.                 throw new IllegalStateException("Not allowed to access field '" + field.getName() + "': " + ex); 
  113.             } 
  114.         } 
  115.     } 
  116.     public static void doWithLocalMethods(Class<?> clazz, MethodCallback mc) { 
  117.         Method[] methods = getDeclaredMethods(clazz, false); 
  118.         for (Method method : methods) { 
  119.             try { 
  120.                 mc.doWith(method); 
  121.             } catch (IllegalAccessException ex) { 
  122.                 throw new IllegalStateException("Not allowed to access method '" + method.getName() + "': " + ex); 
  123.             } 
  124.         } 
  125.     } 

5 填充属性

在这里的属性填充会利用上面的缓存中之间取值进行属性的注入

  1. public class AutowiredAnnotationBeanPostProcessor { 
  2.     public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) { 
  3.         // 这里会直接从缓存中(injectionMetadataCache)获取 
  4.         InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs); 
  5.         // 属性的填充注入 
  6.         metadata.inject(bean, beanName, pvs); 
  7.         return pvs; 
  8.     } 
  9.     private InjectionMetadata findAutowiringMetadata(String beanName, Class<?> clazz, @Nullable PropertyValues pvs) { 
  10.         // Fall back to class name as cache keyfor backwards compatibility with custom callers. 
  11.         String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName()); 
  12.         // Quick check on the concurrent map firstwith minimal locking. 
  13.         InjectionMetadata metadata = this.injectionMetadataCache.get(cacheKey); 
  14.         if (InjectionMetadata.needsRefresh(metadata, clazz)) { 
  15.             synchronized (this.injectionMetadataCache) { 
  16.                 metadata = this.injectionMetadataCache.get(cacheKey); 
  17.                 if (InjectionMetadata.needsRefresh(metadata, clazz)) { 
  18.                     if (metadata != null) { 
  19.                         metadata.clear(pvs); 
  20.                     } 
  21.                     metadata = buildAutowiringMetadata(clazz); 
  22.                     this.injectionMetadataCache.put(cacheKey, metadata); 
  23.                 } 
  24.             } 
  25.         } 
  26.         return metadata; 
  27.     } 

以上就是

MergedBeanDefinitionPostProcessor处理器的作用了。

原文链接:https://www.toutiao.com/a7002388973628801544/