一提起配置类,大家第一个想到的一定是

    1. @Configuration
    2. @ComponentScan("org.wesoft.spring.scan")
    3. public class AppConfig {
    4. }

    没错,这的确是一个配置类,这是类全类名为 AnnotatedGenericBeanDefinition,那么 Spring 是如何进行解析的呢?

    代码跟踪链如下:

    1. public void refresh() throws BeansException, IllegalStateException {
    2. // 省略代码无数...
    3. invokeBeanFactoryPostProcessors(beanFactory);
    4. // 省略代码无数...
    5. }
    6. protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
    7. // 关键代码:getBeanFactoryPostProcessors() 正常情况下是空
    8. // 除非手工通过 ac.addBeanFactoryPostProcessor() 添加
    9. PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
    10. // 省略代码无数...
    11. }
    1. public static void invokeBeanFactoryPostProcessors(
    2. ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {
    3. // 省略代码无数...
    4. String[] postProcessorNames =
    5. beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
    6. for (String ppName : postProcessorNames) {
    7. // 是否实现了 PriorityOrdered 接口(PriorityOrdered 接口,同时又继承了 PriorityOrdered 接口)
    8. if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
    9. // 加入当前需要执行的集合中,执行完会清空该集合
    10. // 为什么要放到集合中?是防止程序员也会提供一个实现
    11. // beanFactory.getBean(),1、从容器中直接拿 bean,2、如果拿不到会实例化该 bean
    12. // 关键代码:beanFactory.getBean() 会返回一个 ConfigurationClassPostProcessor 类
    13. currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
    14. // 找到的 bean 将名字放入 processedBeans 集合中,后面会用这个集合进行判断,是否执行过,就不再进行执行
    15. processedBeans.add(ppName);
    16. }
    17. }
    18. // 排序
    19. sortPostProcessors(currentRegistryProcessors, beanFactory);
    20. // 将所有的 bean 放入 registryProcessors 集合
    21. registryProcessors.addAll(currentRegistryProcessors);
    22. // ★★★ 执行 ConfigurationClassPostProcessor 的 postProcessBeanDefinitionRegistry 方法
    23. // 因为只有 ConfigurationClassPostProcessor 继承了 BeanDefinitionRegistryPostProcessor
    24. // 该方法完成以后,所有的 bean 都会被扫描出来放入 beanDefinitionMap 中
    25. // 老版的 mybatis 就是通过这里入手,完成的扫描
    26. invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
    27. // 清空当前需要执行的集合清空
    28. currentRegistryProcessors.clear();
    29. // 省略代码无数...
    30. }

    首先拿到所有的 BD,此时的 BD,只有开天辟地的 5 个内置 BD 和一个手工注册的 AppConfig,然后进行循环判断,先看这个类是否被解析过,如果没有被解析过,检查并解析这个类,也就是 ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory) 这个方法,当解析完成后,就开始 parser.parse(candidates) 解析了

    1. public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
    2. List<BeanDefinitionHolder> configCandidates = new ArrayList<>();
    3. // 获取所有 内置的 5 个 BD 和 手动 register 进去的(AppConfig.class)
    4. String[] candidateNames = registry.getBeanDefinitionNames();
    5. // 寻找 @Configuration 的类
    6. for (String beanName : candidateNames) {
    7. // 获取 BD
    8. BeanDefinition beanDef = registry.getBeanDefinition(beanName);
    9. // 判断有没有被解析
    10. // ★ 如果这个类已经被解析了,且配置类上加了 @Configuration,就是 full
    11. // ★ 如果这个类已经被解析了,且配置类上没加 @Configuration,就是 lite
    12. // 第一次进来的时候,这个类并没有被解析,所以不会进来
    13. if (ConfigurationClassUtils.isFullConfigurationClass(beanDef) ||
    14. ConfigurationClassUtils.isLiteConfigurationClass(beanDef)) {
    15. if (logger.isDebugEnabled()) {
    16. logger.debug("Bean definition has already been processed as a configuration class: " + beanDef);
    17. }
    18. }
    19. // ★★★ 检查 这个类是不是 AnnotatedGenericBeanDefinition
    20. // ★★★ 同时会给这个类的 attribute 添加一个属性 key = configurationClass,value = full 或者 lite,即标记这个类已经解析过了
    21. else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) {
    22. // ★ 解析成功,加入到已经解析的配置类集合中
    23. configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));
    24. }
    25. }
    26. // Return immediately if no @Configuration classes were found
    27. if (configCandidates.isEmpty()) {
    28. return;
    29. }
    30. // Sort by previously determined @Order value, if applicable
    31. configCandidates.sort((bd1, bd2) -> {
    32. int i1 = ConfigurationClassUtils.getOrder(bd1.getBeanDefinition());
    33. int i2 = ConfigurationClassUtils.getOrder(bd2.getBeanDefinition());
    34. return Integer.compare(i1, i2);
    35. });
    36. // Detect any custom bean name generation strategy supplied through the enclosing application context
    37. SingletonBeanRegistry sbr = null;
    38. if (registry instanceof SingletonBeanRegistry) {
    39. sbr = (SingletonBeanRegistry) registry;
    40. if (!this.localBeanNameGeneratorSet) {
    41. BeanNameGenerator generator = (BeanNameGenerator) sbr.getSingleton(CONFIGURATION_BEAN_NAME_GENERATOR);
    42. if (generator != null) {
    43. this.componentScanBeanNameGenerator = generator;
    44. this.importBeanNameGenerator = generator;
    45. }
    46. }
    47. }
    48. if (this.environment == null) {
    49. this.environment = new StandardEnvironment();
    50. }
    51. // Parse each @Configuration class
    52. ConfigurationClassParser parser = new ConfigurationClassParser(
    53. this.metadataReaderFactory, this.problemReporter, this.environment,
    54. this.resourceLoader, this.componentScanBeanNameGenerator, registry);
    55. Set<BeanDefinitionHolder> candidates = new LinkedHashSet<>(configCandidates);
    56. Set<ConfigurationClass> alreadyParsed = new HashSet<>(configCandidates.size());
    57. do {
    58. // ★★★ 关键代码:解析这个类中所有的注解
    59. parser.parse(candidates);
    60. parser.validate();
    61. Set<ConfigurationClass> configClasses = new LinkedHashSet<>(parser.getConfigurationClasses());
    62. configClasses.removeAll(alreadyParsed);
    63. // Read the model and create bean definitions based on its content
    64. if (this.reader == null) {
    65. this.reader = new ConfigurationClassBeanDefinitionReader(
    66. registry, this.sourceExtractor, this.resourceLoader, this.environment,
    67. this.importBeanNameGenerator, parser.getImportRegistry());
    68. }
    69. this.reader.loadBeanDefinitions(configClasses);
    70. alreadyParsed.addAll(configClasses);
    71. candidates.clear();
    72. if (registry.getBeanDefinitionCount() > candidateNames.length) {
    73. String[] newCandidateNames = registry.getBeanDefinitionNames();
    74. Set<String> oldCandidateNames = new HashSet<>(Arrays.asList(candidateNames));
    75. Set<String> alreadyParsedClasses = new HashSet<>();
    76. for (ConfigurationClass configurationClass : alreadyParsed) {
    77. alreadyParsedClasses.add(configurationClass.getMetadata().getClassName());
    78. }
    79. for (String candidateName : newCandidateNames) {
    80. if (!oldCandidateNames.contains(candidateName)) {
    81. BeanDefinition bd = registry.getBeanDefinition(candidateName);
    82. if (ConfigurationClassUtils.checkConfigurationClassCandidate(bd, this.metadataReaderFactory) &&
    83. !alreadyParsedClasses.contains(bd.getBeanClassName())) {
    84. candidates.add(new BeanDefinitionHolder(bd, candidateName));
    85. }
    86. }
    87. }
    88. candidateNames = newCandidateNames;
    89. }
    90. }
    91. while (!candidates.isEmpty());
    92. // Register the ImportRegistry as a bean in order to support ImportAware @Configuration classes
    93. if (sbr != null && !sbr.containsSingleton(IMPORT_REGISTRY_BEAN_NAME)) {
    94. sbr.registerSingleton(IMPORT_REGISTRY_BEAN_NAME, parser.getImportRegistry());
    95. }
    96. if (this.metadataReaderFactory instanceof CachingMetadataReaderFactory) {
    97. // Clear cache in externally provided MetadataReaderFactory; this is a no-op
    98. // for a shared cache since it'll be cleared by the ApplicationContext.
    99. ((CachingMetadataReaderFactory) this.metadataReaderFactory).clearCache();
    100. }
    101. }

    这里的判断首先看这个 BD 是不是 AnnotatedBeanDefinition 类型,这里就解释了很多问题,前面我们说过,AppConfig 是 AnnotatedGenericBeanDefinition,@Component 标记的 bean 是 ScannedGenericBeanDefinition 类型,@Bean 标记的是 ConfigurationClassBeanDefinition 类型,而这些都是 AnnotatedBeanDefinition 的子类

    1. public static boolean checkConfigurationClassCandidate(
    2. BeanDefinition beanDef, MetadataReaderFactory metadataReaderFactory) {
    3. String className = beanDef.getBeanClassName();
    4. if (className == null || beanDef.getFactoryMethodName() != null) {
    5. return false;
    6. }
    7. AnnotationMetadata metadata;
    8. /*
    9. 一个配置类的 db 类型,就是 AnnotatedGenericBeanDefinition extends GenericBeanDefinition implement AnnotatedBeanDefinition
    10. 通常 AnnotatedBeanDefinition 类型的类,就是一个配置类,因为 Spring 会将配置类写死为 AnnotatedGenericBeanDefinition
    11. ★★★ AnnotatedBeanDefinition 的实现类有三个,AnnotatedGenericBeanDefinition,ConfigurationClassBeanDefinition,ScannedGenericBeanDefinition
    12. 就是判断 beanDef 是不是一个配置类,所以也解释了 @Component 里为什么也可以写 @Bean
    13. 因为 @Component 是一个 ScannedGenericBeanDefinition,他是 AnnotatedBeanDefinition 的子类
    14. 而开天辟地的 5 BD 都是 RootBeanDefinition,所以是不会进行解析的
    15. */
    16. if (beanDef instanceof AnnotatedBeanDefinition &&
    17. className.equals(((AnnotatedBeanDefinition) beanDef).getMetadata().getClassName())) {
    18. // Can reuse the pre-parsed metadata from the given BeanDefinition...
    19. // 获取这个类上所有的 注解信息
    20. metadata = ((AnnotatedBeanDefinition) beanDef).getMetadata();
    21. }
    22. else if (beanDef instanceof AbstractBeanDefinition && ((AbstractBeanDefinition) beanDef).hasBeanClass()) {
    23. // Check already loaded Class if present...
    24. // since we possibly can't even load the class file for this Class.
    25. Class<?> beanClass = ((AbstractBeanDefinition) beanDef).getBeanClass();
    26. metadata = new StandardAnnotationMetadata(beanClass, true);
    27. }
    28. else {
    29. try {
    30. MetadataReader metadataReader = metadataReaderFactory.getMetadataReader(className);
    31. metadata = metadataReader.getAnnotationMetadata();
    32. }
    33. catch (IOException ex) {
    34. if (logger.isDebugEnabled()) {
    35. logger.debug("Could not find class file for introspecting configuration annotations: " +
    36. className, ex);
    37. }
    38. return false;
    39. }
    40. }
    41. // 判断是不是一个 加了 @Configuration 的注解类,此时就是一个 full 配置类
    42. if (isFullConfigurationCandidate(metadata)) {
    43. beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_FULL);
    44. }
    45. // 判断是不是一个 没加 @Configuration 的注解类,此时就是一个 lite 配置类
    46. else if (isLiteConfigurationCandidate(metadata)) {
    47. beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_LITE);
    48. }
    49. else {
    50. return false;
    51. }
    52. // It's a full or lite configuration candidate... Let's determine the order value, if any.
    53. Integer order = getOrder(metadata);
    54. if (order != null) {
    55. beanDef.setAttribute(ORDER_ATTRIBUTE, order);
    56. }
    57. return true;
    58. }