• Spring核心扩展点BeanDefinitionRegistryPostProcessor源码分析


            我们知道,只要在一个Java类上加上@Component、@Service、@Controller等注解,就可以被加载到Spring容器中,除了以上方式,加了@Bean和@Import好像也可以将对象添加到Spring容器中,究竟Spring是如何实现这些功能的呢?让我们一起来一探究竟。

    一、BeanFactoryPostProcessor后置处理器

            Spring IOC在实例化Bean对象之前,需要先读取Bean的相关属性,保存到BeanDefinition对象中,然后通过BeanDefinition对象,实例化Bean对象。

            如果想修改BeanDefinition对象中的属性,该怎么办呢?

            我们可以通过实现BeanFactoryPostProcessor接口实现。

    1. //可以修改bean信息,但必须在bean实例化之前修改
    2. @FunctionalInterface
    3. public interface BeanFactoryPostProcessor {
    4. /**
    5. * Spring自动加载的某个BeanFactoryPostProcessor用于执行cglib动态代理
    6. */
    7. void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;
    8. }

    (1)BeanFactoryPostProcessor的执行时机

            所有的BeanDefinitionPostProcessor后置处理器都是在spring的核心方法refresh()的invokeBeanFactoryPostProcessors(beanFactory);方法中执行的,主要用于修改BeanDefinition的属性信息。

    1. //spring最主要的方法,context(上下文刷新)
    2. @Override
    3. public void refresh() throws BeansException, IllegalStateException {
    4. synchronized (this.startupShutdownMonitor) {
    5. StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");
    6. /**
    7. * context刷新前的准备工作:主要是一些初始状态的赋值,环境配置的获取等
    8. *
    9. */
    10. // Prepare this context for refreshing.
    11. prepareRefresh();
    12. /**
    13. * 获取一个新的BeanFactory:如果已经context中存在BeanFactory,关闭该BeanFactory(先销毁工厂中的bean),再
    14. * 重新创建一个BeanFactory(DefaultListableBeanFactory类型)
    15. *
    16. */
    17. // Tell the subclass to refresh the internal bean factory.
    18. ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
    19. /**
    20. * beanFactory的准备工作,创将一个标准的工厂(设置一些初始状态和初始值)
    21. */
    22. // Prepare the bean factory for use in this context.
    23. prepareBeanFactory(beanFactory);
    24. try {
    25. /**
    26. * 添加BeanFactory的增强器,留给用户扩展
    27. */
    28. // Allows post-processing of the bean factory in context subclasses.
    29. postProcessBeanFactory(beanFactory);
    30. StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
    31. /**
    32. * 执行BeanFactory中注册的BeanFactoryPostProcessor的相关逻辑
    33. */
    34. // Invoke factory processors registered as beans in the context.
    35. //完成所谓的扫描和parse(解析,将类变成beanDefinition)
    36. // springboot的自动装配是在该方法执行的
    37. invokeBeanFactoryPostProcessors(beanFactory);
    38. /**
    39. * 注册bean的增强器(BeanPostProcessor)
    40. */
    41. // Register bean processors that intercept bean creation.
    42. registerBeanPostProcessors(beanFactory);
    43. beanPostProcess.end();
    44. /**
    45. * 国际化处理
    46. */
    47. // Initialize message source for this context.
    48. initMessageSource();
    49. /**
    50. * 初始化应用事件广播器
    51. */
    52. // Initialize event multicaster for this context.
    53. initApplicationEventMulticaster();
    54. /**
    55. *在特定的上下文子类中初始化其他特殊bean,留给用户实现
    56. */
    57. // Initialize other special beans in specific context subclasses.
    58. onRefresh();
    59. /**
    60. * 往广播器中注册监听器
    61. */
    62. // Check for listener beans and register them.
    63. registerListeners();
    64. /**
    65. * 完成单例bean的初始化,同时也会执行registerBeanPostProcessors()时注册的beanPostProcessor
    66. */
    67. // Instantiate all remaining (non-lazy-init) singletons.
    68. //开始实例化单例的类(需要validate和life)
    69. finishBeanFactoryInitialization(beanFactory);
    70. // Last step: publish corresponding event.
    71. // springboot启动Tomcat
    72. finishRefresh();
    73. }
    74. catch (BeansException ex) {
    75. if (logger.isWarnEnabled()) {
    76. logger.warn("Exception encountered during context initialization - " +
    77. "cancelling refresh attempt: " + ex);
    78. }
    79. // Destroy already created singletons to avoid dangling resources.
    80. destroyBeans();
    81. // Reset 'active' flag.
    82. cancelRefresh(ex);
    83. // Propagate exception to caller.
    84. throw ex;
    85. }
    86. finally {
    87. // Reset common introspection caches in Spring's core, since we
    88. // might not ever need metadata for singleton beans anymore...
    89. resetCommonCaches();
    90. contextRefresh.end();
    91. }
    92. }
    93. }

    (2)代码实现

    1. public class SupplierObj{
    2. private String version;
    3. private int num;
    4. public SupplierObj() {
    5. }
    6. public String getVersion() {
    7. return version;
    8. }
    9. public void setVersion(String version) {
    10. this.version = version;
    11. }
    12. public int getNum() {
    13. return num;
    14. }
    15. public void setNum(int num) {
    16. this.num = num;
    17. }
    18. @Override
    19. public String toString() {
    20. return "SupplierObj{" +
    21. "version='" + version + '\'' +
    22. ", num=" + num +
    23. '}';
    24. }
    25. }

               这里设置属性version的值为”1.0.0“。

    1. "supplierObj" class="cn.crazy.newInstance.SupplierObj" >
    2. "num" value="12">
    3. "version" value="1.0.0">

            在这个接口里我们可以修改BeanDefinition的所有属性值,从而间接达到修改bean的信息的效果。

    1. public class MyPostProcessor implements BeanFactoryPostProcessor {
    2. @Override
    3. public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
    4. GenericBeanDefinition beanDefinition = (GenericBeanDefinition)beanFactory.getBeanDefinition("supplierObj");
    5. //beanDefinition.getConstructorArgumentValues().addIndexedArgumentValue();
    6. // 通过Supplier实现对象的实例化
    7. beanDefinition.setInstanceSupplier(() -> {
    8. SupplierObj supplierObj1 = new SupplierObj();
    9. return supplierObj1;
    10. });
    11. beanDefinition.getPropertyValues().addPropertyValue("version","通过BeanFactoryPostProcessor修订的版本0.0.2");
    12. }
    13. }

    控制台输出:

    supplierObj = SupplierObj{version='通过BeanFactoryPostProcessor修订的版本0.0.2',  num=12}

    (二)核心接口BeanDefinitionRegistryPostProcessor

            见名知义,这个后置处理器可以手动控制BeanDefinition的创建和注册。BeanDefinitionRegistryPostProcessor接口继承了BeanFactoryPostProcessor接口。

    1. // BeanDefinitionRegistryPostProcessor可以注册更多的beanDefinition
    2. public interface BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor {
    3. /**
    4. * 在其标准初始化之后修改应用程序上下文的内部beanDefinition定义注册表
    5. */
    6. void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException;
    7. }

            查看Spring源码中关于BeanDefinitionRegistryPostProcessor 的实现类,其中ConfigurationClassPostProcessor是很重要的实现类。

            我们直接通过refresh()的invokeBeanFactoryPostProcessors(beanFactory)方法进入,查看所有BeanFactoryPostProcessor的执行。

    1. // 实例化并调用所有已注册的BeanFactoryPostProcessorBean;
    2. protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
    3. //getBeanFactoryPostProcessors()默认为空,可以通过context.addBeanFactoryPostProcessor();设置值
    4. // 代码块一:
    5. PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
    6. // Detect a LoadTimeWeaver and prepare for weaving, if found in the meantime
    7. // (e.g. through an @Bean method registered by ConfigurationClassPostProcessor)
    8. if (!IN_NATIVE_IMAGE && beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
    9. beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
    10. beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
    11. }
    12. }

    (1)代码块一:invokeBeanFactoryPostProcessors(),执行所有的BeanFactoryPostProcessors接口。

            其中这个方法有一个参数是通过getBeanFactoryPostProcessors()传入的,其默认为空,可以通过context.addBeanFactoryPostProcessor();设置值。

            这个方法也有很多中间变量,我们先把这些变量的作用简单说明下。

    • Set processedBeans :存放所有满足条件的BeanDefinitionRegistryPostProcessor实现类的名称。
    • List regularPostProcessors :存放标准的BeanFactoryPostProcessor实现类的集合(只实现了BeanFactoryPostProcessor接口的实现类)。
    • List registryProcessors:存放BeanDefinitionRegistryPostProcessor实现类的集合。
    • List currentRegistryProcessors:存放当前策略下执行的BeanDefinitionRegistryPostProcessor的集合。
    • String[] postProcessorNames:Spring容器中所有BeanDefinitionRegistryPostProcessor类型的postProcessor对应的名字(beanName)。
    • boolean reiterate:重复标识,初始值为true,因为BeanDefinitionRegistryPostProcessor的postProcessBeanDefinitionRegistry方法可能注册了BeanDefinitionRegistryPostProcessor类型的bd,直到调用完所有BeanDefinitionRegistryPostProcessors,不会出现新的BeanDefinitionRegistryPostProcessors时,设置为false。
    • List priorityOrderedPostProcessors:存放实现了PriorityOrdered接口的BeanFactoryPostProcessor。
    • List orderedPostProcessorNames :存放实现了Ordered接口的BeanFactoryPostProcessor。
    • List nonOrderedPostProcessorNames:存放即没有实现PriorityOrdered接口也没有实现Ordered接口的BeanFactoryPostProcessor。

            这个方法大致总结为:

            1)如果方法参数中beanFactoryPostProcessors不为null,遍历beanFactoryPostProcessors。

            a. 如果其中的processor是BeanDefinitionRegistryPostProcessor类型。

            向上转型为BeanDefinitionRegistryPostProcessor类型,并执行其接口方法postProcessBeanDefinitionRegistry,同时将该processor加入registryProcessors集合。

            b. 如果其中的processor不是BeanDefinitionRegistryPostProcessor类型。

            将该processor加入regularPostProcessors集合。

            beanFactoryPostProcessors默认为空,可以通过context.addBeanFactoryPostProcessor();设置值。

            2)找到Spring容器中所有BeanDefinitionRegistryPostProcessor类型的postProcessor对应的名字,保存到字符串数组postProcessorNames中,遍历这个数组(这时只会找到Spring自己添加的)

            3)如果其中的processor是PriorityOrdered接口的实现类,从容器中getBean(postProcessorName)获取对应的BeanDefinitionRegistryPostProcessor,并将其放入currentRegistryProcessors * 同时将postProcessorName放入processedBeans集合。(这里不用担心会重复执行beanFactoryPostProcessors的processor,它是直接传入的值,并没有注册到容器中)遍历完成后,对currentRegistryProcessors进行排序,将currentRegistryProcessors中的元素全部加入registryProcessors集合中。遍历执行currentRegistryProcessors元素的postProcessBeanDefinitionRegistry(), *然后清空currentRegistryProcessors集合。

            4)重复步骤2,这是因为步骤3中的processor执行postProcessBeanDefinitionRegistry()方法时可能往容器中注册了BeanDefinitionRegistryPostProcessor类型的beanDefinition。

            5)如果其中的processor对应的name在processedBeans中不存在,且是Ordered接口的实现类,后续逻辑与步骤3一致。

            6)维护一个reiterate重复标识,初始值为true,进入while(reiterate),循环内容为执行步骤7

            7)将reiterate设置为false,重复步骤2,如果其中的processor对应的name在processedBeans中不存在,设置reiterate为true,后续逻辑与步骤3一致,进入下一轮循环,直到所有的beanName都在processedBeans中(没有找到新的BeanDefinitionRegistryPostProcessor类型的beanDefinition),结束while循环。

            8)遍历registryProcessors集合,执行BeanDefinitionRegistryPostProcessor类型的postProcessor的postProcessBeanFactory()方法。

             9)遍历regularPostProcessors集合,执行不是BeanDefinitionRegistryPostProcessor类型的postProcessor的postProcessBeanFactory()方法。

            10)找到Spring容器中所有BeanFactoryPostProcessor类型的postProcessor对应的名字,保存到字符串数组postProcessorNames中,遍历这个数组。(这里也是我们扩展的BeanFactoryPostProcessor的执行时机)

    ……

     BeanFactoryPostProcessor的处理逻辑与上述处理BeanDefinitionRegistryPostProcessor时类似,就不过多描述了。 也是先找PriorityOrdered接口的实现类,再找Ordered接口的实现类,最后找不是前面两种的普通实现类,放入对应的集合,排序,遍历执行接口方法

    ……

    1. public static void invokeBeanFactoryPostProcessors(
    2. ConfigurableListableBeanFactory beanFactory, List beanFactoryPostProcessors) {
    3. // Invoke BeanDefinitionRegistryPostProcessors first, if any.
    4. Set processedBeans = new HashSet<>();
    5. if (beanFactory instanceof BeanDefinitionRegistry) {
    6. BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
    7. //存放标准的BeanFactoryPostProcessor的集合(只实现了BeanFactoryPostProcessor接口的实现类)
    8. List regularPostProcessors = new ArrayList<>();
    9. //存放BeanDefinitionRegistryPostProcessor的集合
    10. List registryProcessors = new ArrayList<>();
    11. //beanFactoryPostProcessors默认为空,可自己扩展
    12. for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
    13. //先执行实现了BeanDefinitionRegistryPostProcessor接口的实现类中的postProcessBeanDefinitionRegistry()方法
    14. if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
    15. //向上转型
    16. BeanDefinitionRegistryPostProcessor registryProcessor =
    17. (BeanDefinitionRegistryPostProcessor) postProcessor;
    18. registryProcessor.postProcessBeanDefinitionRegistry(registry);
    19. registryProcessors.add(registryProcessor);
    20. }
    21. else {
    22. //不是BeanDefinitionRegistryPostProcessor类型的postProcessor
    23. regularPostProcessors.add(postProcessor);
    24. }
    25. }
    26. // Do not initialize FactoryBeans here: We need to leave all regular beans
    27. // uninitialized to let the bean factory post-processors apply to them!
    28. // Separate between BeanDefinitionRegistryPostProcessors that implement
    29. // PriorityOrdered, Ordered, and the rest.
    30. // 存放当前执行的BeanDefinitionRegistryPostProcessor
    31. List currentRegistryProcessors = new ArrayList<>();
    32. // First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered.
    33. //找到spring容器中所有BeanDefinitionRegistryPostProcessor类型的postProcessor对应的名字
    34. // 代码块二:默认的BeanDefinitionRegistryPostProcessors的注入时机
    35. //为什么只有一个?怎么来的?Spring在容器初始化时会自动注入一些必要的bean
    36. String[] postProcessorNames =
    37. beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
    38. for (String ppName : postProcessorNames) {
    39. //找实现了PriorityOrdered接口的实现类
    40. if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
    41. //当前需要执行BeanDefinitionRegistryPostProcessor,执行完就会被清空
    42. //为什么能beanFactory.getBean()?虽然spring还没有实例化系统中bean,但是spring会提前实例化必须的bean()
    43. //为什么不直接new,而是选择getBean?有时可能程序员不使用系统默认的实现,可以自己指定实现
    44. /**
    45. * * @see AnnotatedBeanDefinitionReader#AnnotatedBeanDefinitionReader(BeanDefinitionRegistry, Environment)
    46. */
    47. currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
    48. //将找到的Processor对应的名字放入processedBeans,方便后续根据名字判断
    49. processedBeans.add(ppName);
    50. }
    51. }
    52. // 代码块三:对后置处理器进行排序
    53. sortPostProcessors(currentRegistryProcessors, beanFactory);
    54. //将满足条件的Processors对象放入registryProcessors
    55. registryProcessors.addAll(currentRegistryProcessors);
    56. // Spring默认的后置处理器在这个方法里完成扫描
    57. // 代码块四:执行实现了PriorityOrdered接口的后置处理器的接口方法
    58. invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup());
    59. currentRegistryProcessors.clear();
    60. // Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered.
    61. postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
    62. for (String ppName : postProcessorNames) {
    63. //找实现了Ordered接口的实现类
    64. if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {
    65. currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
    66. processedBeans.add(ppName);
    67. }
    68. }
    69. sortPostProcessors(currentRegistryProcessors, beanFactory);
    70. registryProcessors.addAll(currentRegistryProcessors);
    71. // 执行实现了
    72. invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup());
    73. currentRegistryProcessors.clear();
    74. // Finally, invoke all other BeanDefinitionRegistryPostProcessors until no further ones appear.
    75. boolean reiterate = true;
    76. while (reiterate) {
    77. reiterate = false;
    78. postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
    79. for (String ppName : postProcessorNames) {
    80. //找非PriorityOrdered及非Ordered实现类对应BeanDefinitionRegistryPostProcessor
    81. if (!processedBeans.contains(ppName)) {
    82. currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
    83. processedBeans.add(ppName);
    84. //为什么设置为true
    85. //因为BeanDefinitionRegistryPostProcessor的postProcessBeanDefinitionRegistry方法可能注册了BeanDefinitionRegistryPostProcessor类型的bd
    86. reiterate = true;
    87. }
    88. }
    89. sortPostProcessors(currentRegistryProcessors, beanFactory);
    90. registryProcessors.addAll(currentRegistryProcessors);
    91. invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup());
    92. currentRegistryProcessors.clear();
    93. }
    94. // Now, invoke the postProcessBeanFactory callback of all processors handled so far.
    95. //执行BeanDefinitionRegistryPostProcessor类型的postProcessor的postProcessBeanFactory()方法
    96. invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
    97. //执行不是BeanDefinitionRegistryPostProcessor类型的postProcessor的postProcessBeanFactory()方法
    98. invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
    99. }
    100. else {
    101. // Invoke factory processors registered with the context instance.
    102. invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
    103. }
    104. // Do not initialize FactoryBeans here: We need to leave all regular beans
    105. // uninitialized to let the bean factory post-processors apply to them!
    106. //通过扫描找到的BeanFactoryPostProcessor,加了注解(@Component)的后置处理器
    107. String[] postProcessorNames =
    108. beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);
    109. // Separate between BeanFactoryPostProcessors that implement PriorityOrdered,
    110. // Ordered, and the rest.
    111. List priorityOrderedPostProcessors = new ArrayList<>();
    112. List orderedPostProcessorNames = new ArrayList<>();
    113. List nonOrderedPostProcessorNames = new ArrayList<>();
    114. for (String ppName : postProcessorNames) {
    115. if (processedBeans.contains(ppName)) {
    116. // skip - already processed in first phase above
    117. }
    118. else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
    119. priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
    120. }
    121. else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
    122. orderedPostProcessorNames.add(ppName);
    123. }
    124. else {
    125. nonOrderedPostProcessorNames.add(ppName);
    126. }
    127. }
    128. // First, invoke the BeanFactoryPostProcessors that implement PriorityOrdered.
    129. sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
    130. invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);
    131. // Next, invoke the BeanFactoryPostProcessors that implement Ordered.
    132. List orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());
    133. for (String postProcessorName : orderedPostProcessorNames) {
    134. orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
    135. }
    136. sortPostProcessors(orderedPostProcessors, beanFactory);
    137. invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);
    138. // Finally, invoke all other BeanFactoryPostProcessors.
    139. List nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());
    140. for (String postProcessorName : nonOrderedPostProcessorNames) {
    141. nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
    142. }
    143. invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);
    144. // Clear cached merged bean definitions since the post-processors might have
    145. // modified the original metadata, e.g. replacing placeholders in values...
    146. beanFactory.clearMetadataCache();
    147. }

    (2)代码块二:默认的BeanDefinitionRegistryPostProcessors的注入时机。

            Spring默认注入的BeanDefinitionRegistryPostProcessors实现类是ConfigurationClassPostProcessor。在创建Spring容器中有一行代码new AnnotatedBeanDefinitionReader(this);Spring会在容器创建的时候自动注入一些必要的组件。

    1. public AnnotationConfigApplicationContext(Class... componentClasses) {
    2. //调用构造函数,完成一些必须bd的注入
    3. this();
    4. //注册配置类,因为配置需要解析,一般不需要自己扫描
    5. //aliasMap.put
    6. //注册一些spring自身的bean,因为有些bean是无法通过扫描得到的
    7. //registerBeanDefinition(String beanName, BeanDefinition beanDefinition) --- this.beanDefinitionMap.put(beanName, beanDefinition);
    8. register(componentClasses);
    9. refresh();
    10. }
    11. public AnnotationConfigApplicationContext() {
    12. StartupStep createAnnotatedBeanDefReader = this.getApplicationStartup().start("spring.context.annotated-bean-reader.create");
    13. // spring会自动注入一些必须的组件
    14. this.reader = new AnnotatedBeanDefinitionReader(this);
    15. createAnnotatedBeanDefReader.end();
    16. //spring提供api用来动态扫描注解
    17. //一般供扩展spring的时候用的
    18. this.scanner = new ClassPathBeanDefinitionScanner(this);
    19. }

            省略中间的一些代码,最终我们可以找到下面这个方法,registerAnnotationConfigProcessors(),在这个方法中往Spring容器中注入了一些BD。

    1. public static Set registerAnnotationConfigProcessors(
    2. BeanDefinitionRegistry registry, @Nullable Object source) {
    3. DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry);
    4. if (beanFactory != null) {
    5. if (!(beanFactory.getDependencyComparator() instanceof AnnotationAwareOrderComparator)) {
    6. beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);
    7. }
    8. if (!(beanFactory.getAutowireCandidateResolver() instanceof ContextAnnotationAutowireCandidateResolver)) {
    9. beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
    10. }
    11. }
    12. Set beanDefs = new LinkedHashSet<>(8);
    13. //初始化一些必要的bd
    14. if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
    15. // 注入ConfigurationClassPostProcessor.class的地方
    16. RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
    17. def.setSource(source);
    18. beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
    19. }
    20. if (!registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
    21. RootBeanDefinition def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);
    22. def.setSource(source);
    23. beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
    24. }
    25. // Check for JSR-250 support, and if present add the CommonAnnotationBeanPostProcessor.
    26. if (jsr250Present && !registry.containsBeanDefinition(COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)) {
    27. RootBeanDefinition def = new RootBeanDefinition(CommonAnnotationBeanPostProcessor.class);
    28. def.setSource(source);
    29. beanDefs.add(registerPostProcessor(registry, def, COMMON_ANNOTATION_PROCESSOR_BEAN_NAME));
    30. }
    31. // Check for JPA support, and if present add the PersistenceAnnotationBeanPostProcessor.
    32. if (jpaPresent && !registry.containsBeanDefinition(PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME)) {
    33. RootBeanDefinition def = new RootBeanDefinition();
    34. try {
    35. def.setBeanClass(ClassUtils.forName(PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME,
    36. AnnotationConfigUtils.class.getClassLoader()));
    37. }
    38. catch (ClassNotFoundException ex) {
    39. throw new IllegalStateException(
    40. "Cannot load optional framework class: " + PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME, ex);
    41. }
    42. def.setSource(source);
    43. beanDefs.add(registerPostProcessor(registry, def, PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME));
    44. }
    45. if (!registry.containsBeanDefinition(EVENT_LISTENER_PROCESSOR_BEAN_NAME)) {
    46. RootBeanDefinition def = new RootBeanDefinition(EventListenerMethodProcessor.class);
    47. def.setSource(source);
    48. beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_PROCESSOR_BEAN_NAME));
    49. }
    50. if (!registry.containsBeanDefinition(EVENT_LISTENER_FACTORY_BEAN_NAME)) {
    51. RootBeanDefinition def = new RootBeanDefinition(DefaultEventListenerFactory.class);
    52. def.setSource(source);
    53. beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_FACTORY_BEAN_NAME));
    54. }
    55. return beanDefs;
    56. }

     (3)代码块三:sortPostProcessors(),对后置处理器进行排序

            通过排序比较器进行排序。

    1. private static void sortPostProcessors(List postProcessors, ConfigurableListableBeanFactory beanFactory) {
    2. // Nothing to sort?
    3. if (postProcessors.size() <= 1) {
    4. return;
    5. }
    6. Comparator comparatorToUse = null;
    7. if (beanFactory instanceof DefaultListableBeanFactory) {
    8. comparatorToUse = ((DefaultListableBeanFactory) beanFactory).getDependencyComparator();
    9. }
    10. if (comparatorToUse == null) {
    11. comparatorToUse = OrderComparator.INSTANCE;
    12. }
    13. postProcessors.sort(comparatorToUse);
    14. }
    15. (4)代码块四:invokeBeanDefinitionRegistryPostProcessors(),执行实现了PriorityOrdered接口的后置处理器的接口方法 。

              Spring核心类ConfigurationClassPostProcessor在这个方法里主要完成项目的扫描解析的功能。

      1. @Override
      2. public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
      3. // 计算registry的hashCode
      4. int registryId = System.identityHashCode(registry);
      5. if (this.registriesPostProcessed.contains(registryId)) {
      6. throw new IllegalStateException(
      7. "postProcessBeanDefinitionRegistry already called on this post-processor against " + registry);
      8. }
      9. if (this.factoriesPostProcessed.contains(registryId)) {
      10. throw new IllegalStateException(
      11. "postProcessBeanFactory already called on this post-processor against " + registry);
      12. }
      13. this.registriesPostProcessed.add(registryId);
      14. //代码五:完成扫描的逻辑
      15. processConfigBeanDefinitions(registry);
      16. }

      (5)代码块五:processConfigBeanDefinitions(),构建和验证配置类,完成配置类的扫描。

              这个方法大致总结为:

              1)创建一个configCandidates集合变量,存放候选配置类。获取容器中所有的beanDefinition对应的beanName作为候选对象(candidateNames)。(取调用register()加入的bd和spring内置的bd(spring提前初始化的bd))。

              2)遍历candidateNames,获取对应的beanDefinition,判断这个beanDefinition是否被解析过(解析过的配置类ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTE有值),判断这个beanDefinition是否候选配置类对象,如果是,添加到configCandidates候选配置类集合中。

              3)对configCandidates候选配置类集合进行排序,并将其封装到candidates集合中。创建配置类解析器对candidates集合中的候选对象进行解析,并对解析出来的结果进行验证。

              4)注册所有通过配置类找到的需要注册到容器中的元素(需转换为BD对象后再进行注册)。清空candidates集合。

              5)因为会新注册一些bd到容器中,需要对新注册进来的那部分bd继续进行解析。(将新注册的符合条件的bd加入candidates集合,如果candidates为空,说明完成所有候选配置类的解析。)

      1. public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
      2. // 将配置类放入这个候选配置类集合
      3. List configCandidates = new ArrayList<>();
      4. //获取调用register()加入bd和spring内置的bd(spring提前初始化的bd)
      5. String[] candidateNames = registry.getBeanDefinitionNames();
      6. for (String beanName : candidateNames) {
      7. BeanDefinition beanDef = registry.getBeanDefinition(beanName);
      8. //这个类是否被解析过(解析过的配置类ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTE有值)
      9. if (beanDef.getAttribute(ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTE) != null) {
      10. if (logger.isDebugEnabled()) {
      11. logger.debug("Bean definition has already been processed as a configuration class: " + beanDef);
      12. }
      13. }
      14. //代码六 :判断beanDef是否为配置类
      15. else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) {
      16. // 构建BeanDefinitionHolder对象后加入configCandidates集合
      17. configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));
      18. }
      19. }
      20. // Return immediately if no @Configuration classes were found
      21. if (configCandidates.isEmpty()) {
      22. return;
      23. }
      24. // 对集合元素进行排序
      25. // Sort by previously determined @Order value, if applicable
      26. configCandidates.sort((bd1, bd2) -> {
      27. int i1 = ConfigurationClassUtils.getOrder(bd1.getBeanDefinition());
      28. int i2 = ConfigurationClassUtils.getOrder(bd2.getBeanDefinition());
      29. return Integer.compare(i1, i2);
      30. });
      31. // Detect any custom bean name generation strategy supplied through the enclosing application context
      32. SingletonBeanRegistry sbr = null;
      33. if (registry instanceof SingletonBeanRegistry) {
      34. sbr = (SingletonBeanRegistry) registry;
      35. if (!this.localBeanNameGeneratorSet) {
      36. BeanNameGenerator generator = (BeanNameGenerator) sbr.getSingleton(
      37. AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR);
      38. if (generator != null) {
      39. this.componentScanBeanNameGenerator = generator;
      40. this.importBeanNameGenerator = generator;
      41. }
      42. }
      43. }
      44. if (this.environment == null) {
      45. this.environment = new StandardEnvironment();
      46. }
      47. // Parse each @Configuration class
      48. // 解析每个加了@Configuration的类
      49. ConfigurationClassParser parser = new ConfigurationClassParser(
      50. this.metadataReaderFactory, this.problemReporter, this.environment,
      51. this.resourceLoader, this.componentScanBeanNameGenerator, registry);
      52. //将配置类封装到candidates集合
      53. Set candidates = new LinkedHashSet<>(configCandidates);
      54. // 已经完成解析的ConfigurationClass
      55. Set alreadyParsed = new HashSet<>(configCandidates.size());
      56. do {
      57. StartupStep processConfig = this.applicationStartup.start("spring.context.config-classes.parse");
      58. //代码八:完成配置类的解析
      59. parser.parse(candidates);
      60. // 验证在@Configuration属性proxyBeanMethods=true时,其@Bean标记的方法是否符合要求
      61. parser.validate();
      62. Set configClasses = new LinkedHashSet<>(parser.getConfigurationClasses());
      63. configClasses.removeAll(alreadyParsed);
      64. // Read the model and create bean definitions based on its content
      65. if (this.reader == null) {
      66. this.reader = new ConfigurationClassBeanDefinitionReader(
      67. registry, this.sourceExtractor, this.resourceLoader, this.environment,
      68. this.importBeanNameGenerator, parser.getImportRegistry());
      69. }
      70. //其中一个重要的代码是:循环map,执行map中ImportBeanDefinitionRegistrar的registerBeanDefinitions()方法
      71. // 代码二十:注册所有通过配置类找到的需要注册到容器中的元素(需转换为BD对象后再进行注册)
      72. this.reader.loadBeanDefinitions(configClasses);
      73. alreadyParsed.addAll(configClasses);
      74. processConfig.tag("classCount", () -> String.valueOf(configClasses.size())).end();
      75. candidates.clear();
      76. // 因为会新注册一些bd到容器中,需要对新注册进来的那部分bd进行解析
      77. if (registry.getBeanDefinitionCount() > candidateNames.length) {
      78. String[] newCandidateNames = registry.getBeanDefinitionNames();
      79. Set oldCandidateNames = new HashSet<>(Arrays.asList(candidateNames));
      80. Set alreadyParsedClasses = new HashSet<>();
      81. for (ConfigurationClass configurationClass : alreadyParsed) {
      82. alreadyParsedClasses.add(configurationClass.getMetadata().getClassName());
      83. }
      84. for (String candidateName : newCandidateNames) {
      85. if (!oldCandidateNames.contains(candidateName)) {
      86. BeanDefinition bd = registry.getBeanDefinition(candidateName);
      87. if (ConfigurationClassUtils.checkConfigurationClassCandidate(bd, this.metadataReaderFactory) &&
      88. !alreadyParsedClasses.contains(bd.getBeanClassName())) {
      89. candidates.add(new BeanDefinitionHolder(bd, candidateName));
      90. }
      91. }
      92. }
      93. candidateNames = newCandidateNames;
      94. }
      95. }
      96. while (!candidates.isEmpty());
      97. // Register the ImportRegistry as a bean in order to support ImportAware @Configuration classes
      98. if (sbr != null && !sbr.containsSingleton(IMPORT_REGISTRY_BEAN_NAME)) {
      99. sbr.registerSingleton(IMPORT_REGISTRY_BEAN_NAME, parser.getImportRegistry());
      100. }
      101. if (this.metadataReaderFactory instanceof CachingMetadataReaderFactory) {
      102. // Clear cache in externally provided MetadataReaderFactory; this is a no-op
      103. // for a shared cache since it'll be cleared by the ApplicationContext.
      104. ((CachingMetadataReaderFactory) this.metadataReaderFactory).clearCache();
      105. }
      106. }


      (6)代码块六 :checkConfigurationClassCandidate(),检查给定的beanDefinition是否是配置类的候选对象。

              这个方法大致总结如下:

              1)获取beanDefinition的className,判断beanDefinition是否为是AnnotatedBeanDefinition类型且className与元数据中的className一致。

              2)如果是,将beanDefinition转换成AnnotatedBeanDefinition类型,并获取其中的元数据信息。

              3)从元数据中获取@Configuration注解的参数信息,如果为beanDefinition没有加@Configuration注解,返回false。

              4)如果@Configuration的属性proxyBeanMethods的值为true,该配置类为全配置类,并设置

      BD的属性CONFIGURATION_CLASS_ATTRIBUTE的值为CONFIGURATION_CLASS_FULL。

              5)如果@Configuration的属性proxyBeanMethods的值为false,且代码七(步骤7)返回true,

      该配置类为简洁配置类,并设置

      BD的属性CONFIGURATION_CLASS_ATTRIBUTE的值为CONFIGURATION_CLASS_LITE。

              6)BD的属性CONFIGURATION_CLASS_ATTRIBUTE设置完成后,返回true。(BD的属性CONFIGURATION_CLASS_ATTRIBUTE的值如果buwei空,说明该配置类已经被解析过了)

      1. // 检查给定的BeanDefinition是否是配置类的候选对象
      2. // 如果是配置类,设置其配置类的类型(全配置类还是简洁配置类?)
      3. public static boolean checkConfigurationClassCandidate(
      4. BeanDefinition beanDef, MetadataReaderFactory metadataReaderFactory) {
      5. String className = beanDef.getBeanClassName();
      6. if (className == null || beanDef.getFactoryMethodName() != null) {
      7. return false;
      8. }
      9. //保存类的元数据
      10. AnnotationMetadata metadata;
      11. //是AnnotatedBeanDefinition类型的独立的类
      12. if (beanDef instanceof AnnotatedBeanDefinition &&
      13. className.equals(((AnnotatedBeanDefinition) beanDef).getMetadata().getClassName())) {
      14. // Can reuse the pre-parsed metadata from the given BeanDefinition...
      15. metadata = ((AnnotatedBeanDefinition) beanDef).getMetadata();
      16. }
      17. else if (beanDef instanceof AbstractBeanDefinition && ((AbstractBeanDefinition) beanDef).hasBeanClass()) {
      18. // Check already loaded Class if present...
      19. // since we possibly can't even load the class file for this Class.
      20. Class beanClass = ((AbstractBeanDefinition) beanDef).getBeanClass();
      21. // 这几个接口的实现类Spring不认为是候选配置类
      22. if (BeanFactoryPostProcessor.class.isAssignableFrom(beanClass) ||
      23. BeanPostProcessor.class.isAssignableFrom(beanClass) ||
      24. AopInfrastructureBean.class.isAssignableFrom(beanClass) ||
      25. EventListenerFactory.class.isAssignableFrom(beanClass)) {
      26. return false;
      27. }
      28. metadata = AnnotationMetadata.introspect(beanClass);
      29. }
      30. else {
      31. try {
      32. MetadataReader metadataReader = metadataReaderFactory.getMetadataReader(className);
      33. metadata = metadataReader.getAnnotationMetadata();
      34. }
      35. catch (IOException ex) {
      36. if (logger.isDebugEnabled()) {
      37. logger.debug("Could not find class file for introspecting configuration annotations: " +
      38. className, ex);
      39. }
      40. return false;
      41. }
      42. }
      43. //获取类上Configuration注解的参数信息
      44. Map config = metadata.getAnnotationAttributes(Configuration.class.getName());
      45. //boolean proxyBeanMethods() default true;
      46. //CONFIGURATION_CLASS_FULL和CONFIGURATION_CLASS_LITE值的意义?Spring中Aop会用到这个标识
      47. if (config != null && !Boolean.FALSE.equals(config.get("proxyBeanMethods"))) {
      48. // 全配置类或者是完整的配置类
      49. beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_FULL);
      50. }
      51. //Configuration的proxyBeanMethods() = false || [Component、ComponentScan、ImportResource、ImportResource、@Bean方法中一个]则为lite
      52. // 代码块七:检查给定的元数据是否为配置类候选项
      53. else if (config != null || isConfigurationCandidate(metadata)) {
      54. // 简洁的配置类
      55. beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_LITE);
      56. }
      57. else {
      58. return false;
      59. }
      60. // It's a full or lite configuration candidate... Let's determine the order value, if any.
      61. Integer order = getOrder(metadata);
      62. if (order != null) {
      63. beanDef.setAttribute(ORDER_ATTRIBUTE, order);
      64. }
      65. return true;
      66. }

       (7)代码块七:isConfigurationCandidate(metadata),检查给定的metadata元数据是否为配置类候选项。

               当前的元数据是否包含@Component、@ComponentScan、@ImportResource、@Bean方法中一个。是则返回true,否则返回false。

      1. // 检查给定的元数据是否为配置类候选项
      2. public static boolean isConfigurationCandidate(AnnotationMetadata metadata) {
      3. // Do not consider an interface or an annotation...
      4. if (metadata.isInterface()) {
      5. return false;
      6. }
      7. /**
      8. * static {
      9. * candidateIndicators.add(Component.class.getName());
      10. * candidateIndicators.add(ComponentScan.class.getName());
      11. * candidateIndicators.add(Import.class.getName());
      12. * candidateIndicators.add(ImportResource.class.getName());
      13. * }
      14. */
      15. // Any of the typical annotations found?
      16. for (String indicator : candidateIndicators) {
      17. if (metadata.isAnnotated(indicator)) {
      18. return true;
      19. }
      20. }
      21. // Finally, let's look for @Bean methods...
      22. try {
      23. //类里面有包含@Bean的方法
      24. return metadata.hasAnnotatedMethods(Bean.class.getName());
      25. }
      26. catch (Throwable ex) {
      27. if (logger.isDebugEnabled()) {
      28. logger.debug("Failed to introspect @Bean methods on class [" + metadata.getClassName() + "]: " + ex);
      29. }
      30. return false;
      31. }
      32. }

      (8)代码块八:parse()-->processConfigurationClass(),解析配置类。

              这个方法大致总结为:

              1)判断是否满足一些条件配置需要跳过的情况,如果是,直接return。

              2)处理多层嵌套Import导入问题及(不同配置类)多次Import(同一配置类)问题。

              3)递归地处理配置类及其超类的层次结构,封装成SourceClass。

              4)解析@Configuration配置类,解析完成后将其放入this.configurationClasses中,这就是为什么通过别的配置类@Import的配置类在这个方法获取缓存时(this.configurationClasses.get())会有值。
                  

      1. // 解析配置类
      2. public void parse(Set configCandidates) {
      3. for (BeanDefinitionHolder holder : configCandidates) {
      4. BeanDefinition bd = holder.getBeanDefinition();
      5. try {
      6. if (bd instanceof AnnotatedBeanDefinition) {
      7. // 解析AnnotatedBeanDefinition类型的bd
      8. parse(((AnnotatedBeanDefinition) bd).getMetadata(), holder.getBeanName());
      9. }
      10. //省略其他类型bd的解析逻辑,我们选择比较经典的AnnotatedBeanDefinition类型的bd进行源码解析
      11. ……
      12. }
      13. this.deferredImportSelectorHandler.process();
      14. }
      15. // 解析AnnotatedBeanDefinition类型的bd
      16. protected final void parse(AnnotationMetadata metadata, String beanName) throws IOException {
      17. processConfigurationClass(new ConfigurationClass(metadata, beanName), DEFAULT_EXCLUSION_FILTER);
      18. }
      19. // 处理配置类
      20. protected void processConfigurationClass(ConfigurationClass configClass, Predicate filter) throws IOException {
      21. // 跳过某些条件配置生效的情况
      22. if (this.conditionEvaluator.shouldSkip(configClass.getMetadata(), ConfigurationPhase.PARSE_CONFIGURATION)) {
      23. return;
      24. }
      25. // 从缓存中获取
      26. ConfigurationClass existingClass = this.configurationClasses.get(configClass);
      27. if (existingClass != null) {
      28. // 这个配置类是否通过其配置类加@Importe注解引入的
      29. if (configClass.isImported()) {
      30. // 多个配置类通过@Importe注解引入的同一个配置类时,为true
      31. if (existingClass.isImported()) {
      32. existingClass.mergeImportedBy(configClass);
      33. }
      34. // Otherwise ignore new imported config class; existing non-imported class overrides it.
      35. return;
      36. }
      37. else {
      38. // Explicit bean definition found, probably replacing an import.
      39. // Let's remove the old one and go with the new one.
      40. // 嵌套@Importe会进入这个方法
      41. this.configurationClasses.remove(configClass);
      42. this.knownSuperclasses.values().removeIf(configClass::equals);
      43. }
      44. }
      45. // Recursively process the configuration class and its superclass hierarchy.
      46. SourceClass sourceClass = asSourceClass(configClass, filter);
      47. do {
      48. //doXXX一般都是真正处理逻辑的方法
      49. // 代码十:完成配置类的解析
      50. sourceClass = doProcessConfigurationClass(configClass, sourceClass, filter);
      51. }
      52. while (sourceClass != null);
      53. this.configurationClasses.put(configClass, configClass);
      54. }

      (9)代码块九:asSourceClass()递归地处理配置类及其超类层次结构,封装成SourceClass。

              Spring中的所有一切皆Source,class也是一种Source。

      1. private SourceClass asSourceClass(ConfigurationClass configurationClass, Predicate filter) throws IOException {
      2. AnnotationMetadata metadata = configurationClass.getMetadata();
      3. if (metadata instanceof StandardAnnotationMetadata) {
      4. return asSourceClass(((StandardAnnotationMetadata) metadata).getIntrospectedClass(), filter);
      5. }
      6. return asSourceClass(metadata.getClassName(), filter);
      7. }
      8. public SourceClass(Object source) {
      9. this.source = source;
      10. if (source instanceof Class) {
      11. this.metadata = AnnotationMetadata.introspect((Class) source);
      12. }
      13. else {
      14. this.metadata = ((MetadataReader) source).getAnnotationMetadata();
      15. }
      16. }

       (10)代码块十: doProcessConfigurationClass(),处理配置类的解析。

              这个方法大致总结为:

              1)如果配置类有@Component注解,递归处理其成员也是配置类的情况。

              2)如果配置类有@PropertySource注解,解析相关属性信息,完成配置文件的加载。

              3)如果配置类有@ComponentScans或@ComponentScan注解,借助注解扫描器扫描指定目录下的class文件,找到符合条件的beanDefinition添加到候选集合,并完成注册,返回候选集合。

              4)遍历候选集合中的beanDefinition,如果beanDefinition是配置类,执行解析配置类的代码逻辑。

              5)如果配置类有@Import注解,递归查找@Import中的值,根据class类型不同,进行不同的处理。

              6) 如果配置类有@ImportResource 注解,解析相关属性信息,完成配置文件的加载。

              7)递归获取加了@Bean的方法,并加入this.beanMethods。方便后续将这些method封装成beanDefinition对象。

              8)处理接口,遍历当前configClass实现的所有接口,如果接口中有@Bean标记的方法,将这个方法加入this.beanMethods。

      1. protected final SourceClass doProcessConfigurationClass(
      2. ConfigurationClass configClass, SourceClass sourceClass, Predicate filter)
      3. throws IOException {
      4. // Component配置类的解析
      5. if (configClass.getMetadata().isAnnotated(Component.class.getName())) {
      6. // Recursively process any member (nested) classes first
      7. // 递归处理成员也是配置类的情况
      8. // 递归地处理任何成员(嵌套)类[内部类有加Component、ComponentScan、Import、ImportSource等注解的情况]
      9. processMemberClasses(configClass, sourceClass, filter);
      10. }
      11. // Process any @PropertySource annotations
      12. for (AnnotationAttributes propertySource : AnnotationConfigUtils.attributesForRepeatable(
      13. sourceClass.getMetadata(), PropertySources.class,
      14. org.springframework.context.annotation.PropertySource.class)) {
      15. if (this.environment instanceof ConfigurableEnvironment) {
      16. // 代码十一:处理PropertySources加载配置文件
      17. processPropertySource(propertySource);
      18. }
      19. else {
      20. logger.info("Ignoring @PropertySource annotation on [" + sourceClass.getMetadata().getClassName() +
      21. "]. Reason: Environment must implement ConfigurableEnvironment");
      22. }
      23. }
      24. // 处理@ComponentScan扫描项目路径
      25. // Process any @ComponentScan annotations
      26. Set componentScans = AnnotationConfigUtils.attributesForRepeatable(
      27. sourceClass.getMetadata(), ComponentScans.class, ComponentScan.class);
      28. if (!componentScans.isEmpty() &&
      29. !this.conditionEvaluator.shouldSkip(sourceClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN)) {
      30. for (AnnotationAttributes componentScan : componentScans) {
      31. // 代码十二:解析ComponentScan注解
      32. //扫描解析的逻辑
      33. // The config class is annotated with @ComponentScan -> perform the scan immediately
      34. Set scannedBeanDefinitions =
      35. this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());
      36. // Check the set of scanned definitions for any further config classes and parse recursively if needed
      37. for (BeanDefinitionHolder holder : scannedBeanDefinitions) {
      38. BeanDefinition bdCand = holder.getBeanDefinition().getOriginatingBeanDefinition();
      39. if (bdCand == null) {
      40. bdCand = holder.getBeanDefinition();
      41. }
      42. // 是否为配置类
      43. if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) {
      44. // 解析配置类
      45. parse(bdCand.getBeanClassName(), holder.getBeanName());
      46. }
      47. }
      48. }
      49. }
      50. //代码块十六:处理@Import注解引入的class(mybatis的扩展点)
      51. // Process any @Import annotations
      52. processImports(configClass, sourceClass, getImports(sourceClass), filter, true);
      53. // Process any @ImportResource annotations
      54. // 处理@ImportResource加载配置文件
      55. AnnotationAttributes importResource =
      56. AnnotationConfigUtils.attributesFor(sourceClass.getMetadata(), ImportResource.class);
      57. if (importResource != null) {
      58. String[] resources = importResource.getStringArray("locations");
      59. Classextends BeanDefinitionReader> readerClass = importResource.getClass("reader");
      60. for (String resource : resources) {
      61. String resolvedResource = this.environment.resolveRequiredPlaceholders(resource);
      62. configClass.addImportedResource(resolvedResource, readerClass);
      63. }
      64. }
      65. // Process individual @Bean methods
      66. // 获取加了@Bean的方法,并加入this.beanMethods
      67. Set beanMethods = retrieveBeanMethodMetadata(sourceClass);
      68. for (MethodMetadata methodMetadata : beanMethods) {
      69. configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
      70. }
      71. // 处理接口,遍历当前configClass实现的所有接口,如果接口中有@Bean标记的方法,将这个方法加入this.beanMethods
      72. // Process default methods on interfaces
      73. processInterfaces(configClass, sourceClass);
      74. // Process superclass, if any
      75. if (sourceClass.getMetadata().hasSuperClass()) {
      76. String superclass = sourceClass.getMetadata().getSuperClassName();
      77. if (superclass != null && !superclass.startsWith("java") &&
      78. !this.knownSuperclasses.containsKey(superclass)) {
      79. this.knownSuperclasses.put(superclass, configClass);
      80. // Superclass found, return its annotation metadata and recurse
      81. return sourceClass.getSuperClass();
      82. }
      83. }
      84. // No superclass -> processing is complete
      85. return null;
      86. }

      (11)代码块十一:processPropertySource(),处理PropertySources加载配置文件。

              @PropertySource注解用于指定资源文件读取的位置,它不仅能读取properties文件,也能读取xml文件,并且通过YAML解析器,配合自定义PropertySourceFactory实现解析YAML文件。

      1. private void processPropertySource(AnnotationAttributes propertySource) throws IOException {
      2. // 处理name属性
      3. String name = propertySource.getString("name");
      4. if (!StringUtils.hasLength(name)) {
      5. name = null;
      6. }
      7. // 处理encoding属性
      8. String encoding = propertySource.getString("encoding");
      9. if (!StringUtils.hasLength(encoding)) {
      10. encoding = null;
      11. }
      12. String[] locations = propertySource.getStringArray("value");
      13. Assert.isTrue(locations.length > 0, "At least one @PropertySource(value) location is required");
      14. // 忽略找不到的情况,找不到资源文件不会报错
      15. boolean ignoreResourceNotFound = propertySource.getBoolean("ignoreResourceNotFound");
      16. Classextends PropertySourceFactory> factoryClass = propertySource.getClass("factory");
      17. PropertySourceFactory factory = (factoryClass == PropertySourceFactory.class ?
      18. DEFAULT_PROPERTY_SOURCE_FACTORY : BeanUtils.instantiateClass(factoryClass));
      19. for (String location : locations) {
      20. try {
      21. // 加载资源文件
      22. String resolvedLocation = this.environment.resolveRequiredPlaceholders(location);
      23. Resource resource = this.resourceLoader.getResource(resolvedLocation);
      24. addPropertySource(factory.createPropertySource(name, new EncodedResource(resource, encoding)));
      25. }
      26. catch (IllegalArgumentException | FileNotFoundException | UnknownHostException | SocketException ex) {
      27. // Placeholders not resolvable or resource not found when trying to open it
      28. if (ignoreResourceNotFound) {
      29. if (logger.isInfoEnabled()) {
      30. logger.info("Properties location [" + location + "] not resolvable: " + ex.getMessage());
      31. }
      32. }
      33. else {
      34. throw ex;
      35. }
      36. }
      37. }
      38. }

       (12)代码块十二:parse(),处理@componentScan注解。

              这个方法大致总结为:

              1)创建一个注解扫描器,可以通过@ComponentScan(useDefaultFilters = boolean)决定是否使用spring默认的扫描器TypeFilter。读取注解中的属性信息,完成注解扫描器对应的属性值设置。

              2)通过扫描器扫描basePackages下的class,然后解析成对应的bd。

      1. // 解析@ComponentScan注解
      2. public Set parse(AnnotationAttributes componentScan, final String declaringClass) {
      3. //可以通过@ComponentScan(useDefaultFilters = boolean)决定是否使用spring默认的扫描器
      4. // 创建一个注解扫描器
      5. ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(this.registry,
      6. componentScan.getBoolean("useDefaultFilters"), this.environment, this.resourceLoader);
      7. //读取注解中的属性,完成注解扫描器对应的属性值设置
      8. Classextends BeanNameGenerator> generatorClass = componentScan.getClass("nameGenerator");
      9. boolean useInheritedGenerator = (BeanNameGenerator.class == generatorClass);
      10. scanner.setBeanNameGenerator(useInheritedGenerator ? this.beanNameGenerator :
      11. BeanUtils.instantiateClass(generatorClass));
      12. ScopedProxyMode scopedProxyMode = componentScan.getEnum("scopedProxy");
      13. if (scopedProxyMode != ScopedProxyMode.DEFAULT) {
      14. scanner.setScopedProxyMode(scopedProxyMode);
      15. }
      16. else {
      17. Classextends ScopeMetadataResolver> resolverClass = componentScan.getClass("scopeResolver");
      18. scanner.setScopeMetadataResolver(BeanUtils.instantiateClass(resolverClass));
      19. }
      20. scanner.setResourcePattern(componentScan.getString("resourcePattern"));
      21. for (AnnotationAttributes filter : componentScan.getAnnotationArray("includeFilters")) {
      22. for (TypeFilter typeFilter : typeFiltersFor(filter)) {
      23. scanner.addIncludeFilter(typeFilter);
      24. }
      25. }
      26. for (AnnotationAttributes filter : componentScan.getAnnotationArray("excludeFilters")) {
      27. for (TypeFilter typeFilter : typeFiltersFor(filter)) {
      28. scanner.addExcludeFilter(typeFilter);
      29. }
      30. }
      31. boolean lazyInit = componentScan.getBoolean("lazyInit");
      32. if (lazyInit) {
      33. scanner.getBeanDefinitionDefaults().setLazyInit(true);
      34. }
      35. Set basePackages = new LinkedHashSet<>();
      36. // 扫描的项目路径
      37. String[] basePackagesArray = componentScan.getStringArray("basePackages");
      38. for (String pkg : basePackagesArray) {
      39. String[] tokenized = StringUtils.tokenizeToStringArray(this.environment.resolvePlaceholders(pkg),
      40. ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS);
      41. Collections.addAll(basePackages, tokenized);
      42. }
      43. for (Class clazz : componentScan.getClassArray("basePackageClasses")) {
      44. basePackages.add(ClassUtils.getPackageName(clazz));
      45. }
      46. if (basePackages.isEmpty()) {
      47. basePackages.add(ClassUtils.getPackageName(declaringClass));
      48. }
      49. scanner.addExcludeFilter(new AbstractTypeHierarchyTraversingFilter(false, false) {
      50. @Override
      51. protected boolean matchClassName(String className) {
      52. return declaringClass.equals(className);
      53. }
      54. });
      55. //代码十三:调用doScan()扫描basePackages下的类,然后解析成对应的bd
      56. return scanner.doScan(StringUtils.toStringArray(basePackages));
      57. }

              创建扫描器时默认使用Spring注册的TypeFilters。

      1. public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry, boolean useDefaultFilters,
      2. Environment environment, @Nullable ResourceLoader resourceLoader) {
      3. Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
      4. this.registry = registry;
      5. //关键代码,Spring内部默认为true,使用默认的Filters
      6. if (useDefaultFilters) {
      7. registerDefaultFilters();
      8. }
      9. setEnvironment(environment);
      10. setResourceLoader(resourceLoader);
      11. }
      12. protected void registerDefaultFilters() {
      13. //这里传了一个Component.class
      14. //后续spring扫描一个resource出来之后需要判断他是否合理,核心代码
      15. this.includeFilters.add(new AnnotationTypeFilter(Component.class));
      16. ClassLoader cl = ClassPathScanningCandidateComponentProvider.class.getClassLoader();
      17. try {
      18. this.includeFilters.add(new AnnotationTypeFilter(
      19. ((Classextends Annotation>) ClassUtils.forName("javax.annotation.ManagedBean", cl)), false));
      20. logger.trace("JSR-250 'javax.annotation.ManagedBean' found and supported for component scanning");
      21. }
      22. catch (ClassNotFoundException ex) {
      23. // JSR-250 1.1 API (as included in Java EE 6) not available - simply skip.
      24. }
      25. try {
      26. this.includeFilters.add(new AnnotationTypeFilter(
      27. ((Classextends Annotation>) ClassUtils.forName("javax.inject.Named", cl)), false));
      28. logger.trace("JSR-330 'javax.inject.Named' annotation found and supported for component scanning");
      29. }
      30. catch (ClassNotFoundException ex) {
      31. // JSR-330 API not available - simply skip.
      32. }
      33. }

      (13)代码块十三:doScan(),扫描basePackages下的class,然后解析成对应的bd。

              1)创建一个Set集合变量beanDefinitions,用来存放解析后的beanDefinition。

              2)遍历扫描路径,返回该目录下满足条件的候选集合。

              3)遍历候选集合,获取当前beanDefinition的beanName,并根据beanDefinition的类型设置不同的默认属性。

              4)检查是否需要注册当前beanDefinition,如果容器中不存在beanName对应的组件,则需要注册。根据当前beanDefinition和对应的beanName构建BeanDefinitionHolder对象,将holder对象添加到beanDefinitions集合,并将其注册到容器中(beanDefinitionMap.put(beanName, beanDefinition);)。

      1. protected Set doScan(String... basePackages) {
      2. Assert.notEmpty(basePackages, "At least one base package must be specified");
      3. Set beanDefinitions = new LinkedHashSet<>();
      4. for (String basePackage : basePackages) {
      5. //代码块十四:找到满足条件的候选组件
      6. Set candidates = findCandidateComponents(basePackage);
      7. for (BeanDefinition candidate : candidates) {
      8. ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);
      9. candidate.setScope(scopeMetadata.getScopeName());
      10. String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);
      11. if (candidate instanceof AbstractBeanDefinition) {
      12. // 设置一些默认属性
      13. postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);
      14. }
      15. if (candidate instanceof AnnotatedBeanDefinition) {
      16. // 将注解信息设置为相应的bd属性
      17. AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
      18. }
      19. // 检查是否需要注册candidate,容器中不存在beanName对应的组件
      20. if (checkCandidate(beanName, candidate)) {
      21. BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
      22. definitionHolder =
      23. AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
      24. beanDefinitions.add(definitionHolder);
      25. registerBeanDefinition(definitionHolder, this.registry);
      26. }
      27. }
      28. }
      29. return beanDefinitions;
      30. }

      (14)代码块十四:findCandidateComponents(),找到满足条件的候选组件

              这个方法大致总结为:

              1)获取扫描目录路径,并将该目录下的所有文件封装为Spring中的Source(Source是对URL的扩展,提供了更多获取文件信息的方法)。

              2)遍历所有的source,判断source资源是否可读,如果可读,获取source的元数据信息。

              3)判断元数据中的注解是否满足要求,this.includeFilters中的TypeFilter与metadataReader是否匹配。默认扫描的注解为@Component。

              4)如果匹配,结合元数据和source封装为ScannedGenericBeanDefinition对象,接着判断给定这个BD对象的类型是否符合要求。如果符合要求,将这个BD加入候选集合中,返回这个集合。

      1. public Set findCandidateComponents(String basePackage) {
      2. //如果有添加spring索引辅助jar包,执行这块代码
      3. if (this.componentsIndex != null && indexSupportsIncludeFilters()) {
      4. return addCandidateComponentsFromIndex(this.componentsIndex, basePackage);
      5. }
      6. else {
      7. //默认执行这块代码
      8. return scanCandidateComponents(basePackage);
      9. }
      10. }
      11. //扫描出符合规则的候选组件
      12. private Set scanCandidateComponents(String basePackage) {
      13. Set candidates = new LinkedHashSet<>();
      14. try {
      15. String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX +
      16. resolveBasePackage(basePackage) + '/' + this.resourcePattern;
      17. //Resource扩展了URL,提供了更丰富的功能
      18. Resource[] resources = getResourcePatternResolver().getResources(packageSearchPath);
      19. boolean traceEnabled = logger.isTraceEnabled();
      20. boolean debugEnabled = logger.isDebugEnabled();
      21. // 遍历指定目录下的class
      22. for (Resource resource : resources) {
      23. if (traceEnabled) {
      24. logger.trace("Scanning " + resource);
      25. }
      26. if (resource.isReadable()) {
      27. try {
      28. //类的元数据
      29. MetadataReader metadataReader = getMetadataReaderFactory().getMetadataReader(resource);
      30. //代码十五:判断注解是否满足要求
      31. if (isCandidateComponent(metadataReader)) {
      32. ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader);
      33. sbd.setSource(resource);
      34. //Mybatis的扩展点:Mybatis为什么可以扫描接口
      35. //代码十六 :判断给定bd的类型是否符合要求
      36. if (isCandidateComponent(sbd)) {
      37. if (debugEnabled) {
      38. logger.debug("Identified candidate component class: " + resource);
      39. }
      40. candidates.add(sbd);
      41. }
      42. ……
      43. }
      44. }
      45. catch (IOException ex) {
      46. throw new BeanDefinitionStoreException("I/O failure during classpath scanning", ex);
      47. }
      48. return candidates;
      49. }
      50. protected boolean isCandidateComponent(MetadataReader metadataReader) throws IOException {
      51. for (TypeFilter tf : this.excludeFilters) {
      52. if (tf.match(metadataReader, getMetadataReaderFactory())) {
      53. return false;
      54. }
      55. }
      56. //如果想解析其他注解(Mybatis的Mapper注解),可以往includeFilters中添加对应的注解
      57. //this.includeFilters是否有与metadataReader匹配的TypeFilter
      58. //如果想要在spring中添加自定义扫描器,可以考虑将自定义的扫描加入this.includeFilters集合
      59. for (TypeFilter tf : this.includeFilters) {
      60. if (tf.match(metadataReader, getMetadataReaderFactory())) {
      61. return isConditionMatch(metadataReader);
      62. }
      63. }
      64. return false;
      65. }
      66. protected void registerDefaultFilters() {
      67. //这里传了一个Component.class
      68. //后续spring扫描一个resource出来之后需要判断他是否合理,核心代码
      69. this.includeFilters.add(new AnnotationTypeFilter(Component.class));
      70. ClassLoader cl = ClassPathScanningCandidateComponentProvider.class.getClassLoader();
      71. try {
      72. this.includeFilters.add(new AnnotationTypeFilter(
      73. ((Classextends Annotation>) ClassUtils.forName("javax.annotation.ManagedBean", cl)), false));
      74. logger.trace("JSR-250 'javax.annotation.ManagedBean' found and supported for component scanning");
      75. }
      76. catch (ClassNotFoundException ex) {
      77. // JSR-250 1.1 API (as included in Java EE 6) not available - simply skip.
      78. }
      79. try {
      80. this.includeFilters.add(new AnnotationTypeFilter(
      81. ((Classextends Annotation>) ClassUtils.forName("javax.inject.Named", cl)), false));
      82. logger.trace("JSR-330 'javax.inject.Named' annotation found and supported for component scanning");
      83. }
      84. catch (ClassNotFoundException ex) {
      85. // JSR-330 API not available - simply skip.
      86. }
      87. }

      (15)代码块十五:isCandidateComponent(),判断给定的beanDefinition是否候选组件 。

             方法重载,这两个方法的功能如下:

          (i)this.includeFilters中的TypeFilter与metadataReader是否匹配。

              这里是扫描器的工作原理,自定义的扫描时可以将要扫描的注解类的TypeFilter加入this.includeFilters集合。

      1. protected boolean isCandidateComponent(MetadataReader metadataReader) throws IOException {
      2. for (TypeFilter tf : this.excludeFilters) {
      3. if (tf.match(metadataReader, getMetadataReaderFactory())) {
      4. return false;
      5. }
      6. }
      7. //如果想解析其他注解(Mybatis的Mapper注解),可以往includeFilters中添加对应的注解
      8. //this.includeFilters是否有与metadataReader匹配的TypeFilter
      9. //如果想要在spring中添加自定义扫描器,可以考虑将自定义的扫描加入this.includeFilters集合
      10. for (TypeFilter tf : this.includeFilters) {
      11. if (tf.match(metadataReader, getMetadataReaderFactory())) {
      12. return isConditionMatch(metadataReader);
      13. }
      14. }
      15. return false;
      16. }

              (ii)判断给定的beanDefinition类类型是否满足候选条件

              Spring中的扫描是不能扫描接口的,除非这个接口加了@Lookup注解。我们知道在接口上加Mybatis注解是,能被扫描成Mapper,这首因为Mybatis修改了这个判断。

      1. protected boolean isCandidateComponent(AnnotatedBeanDefinition beanDefinition) {
      2. AnnotationMetadata metadata = beanDefinition.getMetadata();
      3. //判断类类型是否满足候选条件(顶层类或加了@Lookup的抽象类等)
      4. return (metadata.isIndependent() && (metadata.isConcrete() ||
      5. (metadata.isAbstract() && metadata.hasAnnotatedMethods(Lookup.class.getName()))));
      6. }
      7. default boolean isConcrete() {
      8. return !(isInterface() || isAbstract());
      9. }

              isIndependent()判断是一个class是独立的,有两种情况:一.它是top-level的(我们正常创建的类)。 二.它是nested class也就是静态内部类。

              class分为5中类型:

      • top level class

      • nested class (静态内部类)

      • inner class(非静态内部类)

      • local class(在方法内定义的类)

      • anonymous class(匿名类)

      三、处理@Import注解 

              因为上一章节太长了,而且@Import注解比较重要,所有开了一个新的章节来说。使用@Import注解引入的class是很常有的一个功能,同时也是mybatis的扩展点。下面来看看Spring是如何处理@Import注解的。

      1. //代码块十六:处理@Import注解引入的class(mybatis的扩展点)
      2. // Process any @Import annotations
      3. processImports(configClass, sourceClass, getImports(sourceClass), filter, true);
      4. // 返回@Import引入的class
      5. private Set getImports(SourceClass sourceClass) throws IOException {
      6. Set imports = new LinkedHashSet<>();
      7. Set visited = new LinkedHashSet<>();
      8. collectImports(sourceClass, imports, visited);
      9. return imports;
      10. }
      11. //递归收集所有@Import的值
      12. private void collectImports(SourceClass sourceClass, Set imports, Set visited)
      13. throws IOException {
      14. if (visited.add(sourceClass)) {
      15. // 获取class上所有的注解
      16. for (SourceClass annotation : sourceClass.getAnnotations()) {
      17. String annName = annotation.getMetadata().getClassName();
      18. if (!annName.equals(Import.class.getName())) {
      19. // 不是@Import的注解上可能又加了@Import注解,所以要递归查找
      20. collectImports(annotation, imports, visited);
      21. }
      22. }
      23. imports.addAll(sourceClass.getAnnotationAttributes(Import.class.getName(), "value"));
      24. }
      25. }

       (1)代码块十六: processImports(),处理@Import注解(mybatis的扩展点)。

              这个方法大致总结为:

              1)如果importCandidates为null,直接返回。(importCandidates为容器中所有通过@Import导入的class的集合)

              2)进行一些检查,如果检查不通过,报错。

              3)遍历importCandidates,

               a. 如果当前的candidates是ImportSelector类型,反射创建ImportSelector对象,执行该对象的selectImports()方法,将返回值封装成Source集合,递归处理@Import注解。

              b.如果当前的candidates是ImportBeanDefinitionRegistrar类型,通过反射创建ImportBeanDefinitionRegistrar对象,并加入configClass的importBeanDefinitionRegistrars集合中。

              c.如果当前的candidates不是ImportSelector类型,也不是ImportBeanDefinitionRegistrar类型,把它当成@Configuration配置类进行处理。

      1. private void processImports(ConfigurationClass configClass, SourceClass currentSourceClass,
      2. Collection importCandidates, Predicate exclusionFilter,
      3. boolean checkForCircularImports) {
      4. // 如果没有@Import注解,直接返回
      5. if (importCandidates.isEmpty()) {
      6. return;
      7. }
      8. // checkForCircularImports = true
      9. if (checkForCircularImports && isChainedImportOnStack(configClass)) {
      10. // 报错
      11. this.problemReporter.error(new CircularImportProblem(configClass, this.importStack));
      12. }
      13. else {
      14. this.importStack.push(configClass);
      15. try {
      16. // 遍历@Import引入的类
      17. for (SourceClass candidate : importCandidates) {
      18. // 如果candidate是ImportSelector类型
      19. if (candidate.isAssignable(ImportSelector.class)) {
      20. // Candidate class is an ImportSelector -> delegate to it to determine imports
      21. // 返回Class对象,如果是this.source是Class类型直接返回,或者通过this.source得到beanName,通过Class.forName(beanName)返回Class
      22. // 代码十七:获取candidate的Class对象
      23. Class candidateClass = candidate.loadClass();
      24. // 反射创建ImportSelector对象
      25. ImportSelector selector = ParserStrategyUtils.instantiateClass(candidateClass, ImportSelector.class,
      26. this.environment, this.resourceLoader, this.registry);
      27. //exclusionFilter,用于从导入候选对象中排除类
      28. Predicate selectorFilter = selector.getExclusionFilter();
      29. if (selectorFilter != null) {
      30. exclusionFilter = exclusionFilter.or(selectorFilter);
      31. }
      32. // 如果selector是DeferredImportSelector类型,执行默认的ImportSelector的处理
      33. if (selector instanceof DeferredImportSelector) {
      34. this.deferredImportSelectorHandler.handle(configClass, (DeferredImportSelector) selector);
      35. }
      36. else {
      37. // 获取selector.selectImports()的返回值
      38. String[] importClassNames = selector.selectImports(currentSourceClass.getMetadata());
      39. // 封装成Source
      40. Collection importSourceClasses = asSourceClasses(importClassNames, exclusionFilter);
      41. // 递归处理@Import注解
      42. processImports(configClass, currentSourceClass, importSourceClasses, exclusionFilter, false);
      43. }
      44. }
      45. //如果@Import引入了ImportBeanDefinitionRegistrar类型的class,通过反射创建出来,并加入configClass的importBeanDefinitionRegistrars集合中
      46. // @Import注解引入的class能被创建的原因
      47. else if (candidate.isAssignable(ImportBeanDefinitionRegistrar.class)) {
      48. // Candidate class is an ImportBeanDefinitionRegistrar ->
      49. // delegate to it to register additional bean definitions
      50. // 获取candidate的Class对象
      51. Class candidateClass = candidate.loadClass();
      52. //实例化对象
      53. // 代码块十八:通过反射实例化对象
      54. ImportBeanDefinitionRegistrar registrar =
      55. ParserStrategyUtils.instantiateClass(candidateClass, ImportBeanDefinitionRegistrar.class,
      56. this.environment, this.resourceLoader, this.registry);
      57. //将实例化后的对象放入importBeanDefinitionRegistrars集合中(没有立即执行ImportBeanDefinitionRegistrar,后面循环这个map进行执行)
      58. //public void addImportBeanDefinitionRegistrar(ImportBeanDefinitionRegistrar registrar, AnnotationMetadata importingClassMetadata) {
      59. // this.importBeanDefinitionRegistrars.put(registrar, importingClassMetadata);
      60. // }
      61. // 代码十九:将实例化后的对象放入importBeanDefinitionRegistrars集合中
      62. configClass.addImportBeanDefinitionRegistrar(registrar, currentSourceClass.getMetadata());
      63. }
      64. else {
      65. // Candidate class not an ImportSelector or ImportBeanDefinitionRegistrar ->
      66. // process it as an @Configuration class
      67. this.importStack.registerImport(
      68. currentSourceClass.getMetadata(), candidate.getMetadata().getClassName());
      69. // 如果@Import引入的class不是ImportSelector or ImportBeanDefinitionRegistrar,把它当成@Configuration配置类进行处理
      70. processConfigurationClass(candidate.asConfigClass(configClass), exclusionFilter);
      71. }
      72. }
      73. }
      74. catch (BeanDefinitionStoreException ex) {
      75. throw ex;
      76. }
      77. catch (Throwable ex) {
      78. throw new BeanDefinitionStoreException(
      79. "Failed to process import candidates for configuration class [" +
      80. configClass.getMetadata().getClassName() + "]", ex);
      81. }
      82. finally {
      83. this.importStack.pop();
      84. }
      85. }
      86. }

      (2)代码块十七:loadClass(),获取candidate的Class对象。

              返回Class对象,如果是this.source是Class类型直接返回,或者通过this.source得到beanName,通过Class.forName(beanName)返回Class对象。

      1. public Class loadClass() throws ClassNotFoundException {
      2. if (this.source instanceof Class) {
      3. return (Class) this.source;
      4. }
      5. String className = ((MetadataReader) this.source).getClassMetadata().getClassName();
      6. return ClassUtils.forName(className, resourceLoader.getClassLoader());
      7. }

      (3)代码块十八:instantiateClass(),通过反射实例化对象。

      1. static T instantiateClass(Class clazz, Class assignableTo, Environment environment,
      2. ResourceLoader resourceLoader, BeanDefinitionRegistry registry) {
      3. Assert.notNull(clazz, "Class must not be null");
      4. Assert.isAssignable(assignableTo, clazz);
      5. if (clazz.isInterface()) {
      6. throw new BeanInstantiationException(clazz, "Specified class is an interface");
      7. }
      8. ClassLoader classLoader = (registry instanceof ConfigurableBeanFactory ?
      9. ((ConfigurableBeanFactory) registry).getBeanClassLoader() : resourceLoader.getClassLoader());
      10. //通过反射创建clazz对象
      11. T instance = (T) createInstance(clazz, environment, resourceLoader, registry, classLoader);
      12. //扩展点:执行这个实例的awareMethods,这个实例是否有实现xxAware接口
      13. ParserStrategyUtils.invokeAwareMethods(instance, environment, resourceLoader, registry, classLoader);
      14. return instance;
      15. }
      16. private static Object createInstance(Class clazz, Environment environment,
      17. ResourceLoader resourceLoader, BeanDefinitionRegistry registry,
      18. @Nullable ClassLoader classLoader) {
      19. Constructor[] constructors = clazz.getDeclaredConstructors();
      20. if (constructors.length == 1 && constructors[0].getParameterCount() > 0) {
      21. try {
      22. Constructor constructor = constructors[0];
      23. Object[] args = resolveArgs(constructor.getParameterTypes(),
      24. environment, resourceLoader, registry, classLoader);
      25. // 如果只有一个构造器,且是有参构造器,使用这个构造器实例化对象
      26. return BeanUtils.instantiateClass(constructor, args);
      27. }
      28. catch (Exception ex) {
      29. throw new BeanInstantiationException(clazz, "No suitable constructor found", ex);
      30. }
      31. }
      32. // 通过无参构造器实例话对象
      33. return BeanUtils.instantiateClass(clazz);
      34. }

       (4)代码块十九:addImportBeanDefinitionRegistrar(),将实例化后的对象放入importBeanDefinitionRegistrars集合中。

              将实例化后的对象放入importBeanDefinitionRegistrars集合中(没有立即执行ImportBeanDefinitionRegistrar,后面循环这个map进行执行)

      1. public void addImportBeanDefinitionRegistrar(ImportBeanDefinitionRegistrar registrar, AnnotationMetadata importingClassMetadata) {
      2. this.importBeanDefinitionRegistrars.put(registrar, importingClassMetadata);
      3. }

      (5)代码块二十:loadBeanDefinitions(),注册所有通过配置类找到的需要注册到容器中的元素。

      1. public void loadBeanDefinitions(Set configurationModel) {
      2. TrackedConditionEvaluator trackedConditionEvaluator = new TrackedConditionEvaluator();
      3. for (ConfigurationClass configClass : configurationModel) {
      4. loadBeanDefinitionsForConfigurationClass(configClass, trackedConditionEvaluator);
      5. }
      6. }

             这个方法是注册所有通过配置类找到的需要注册到容器中的元数据(或者称为元素合适一些?),将其封装为beanDefinition对象后注册到容器中 。

      1. // 这个方法是注册所有通过配置类找到的需要注册到容器中的元数据(或者称为元素合适一些?),将其封装为bd后注册到容器中
      2. private void loadBeanDefinitionsForConfigurationClass(
      3. ConfigurationClass configClass, TrackedConditionEvaluator trackedConditionEvaluator) {
      4. if (trackedConditionEvaluator.shouldSkip(configClass)) {
      5. String beanName = configClass.getBeanName();
      6. if (StringUtils.hasLength(beanName) && this.registry.containsBeanDefinition(beanName)) {
      7. this.registry.removeBeanDefinition(beanName);
      8. }
      9. this.importRegistry.removeImportingClass(configClass.getMetadata().getClassName());
      10. return;
      11. }
      12. if (configClass.isImported()) {
      13. registerBeanDefinitionForImportedConfigurationClass(configClass);
      14. }
      15. for (BeanMethod beanMethod : configClass.getBeanMethods()) {
      16. // 获取@Bean标记方法对应的元数据,name等封装成相应beanDefinition,注册到容器中
      17. // 代码A
      18. loadBeanDefinitionsForBeanMethod(beanMethod);
      19. }
      20. loadBeanDefinitionsFromImportedResources(configClass.getImportedResources());
      21. // 通过ImportBeanDefinitionRegistrar实例化bd,遍历注册this.importBeanDefinitionRegistrars中的对象
      22. // 代码B
      23. loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars());
      24. }

              我们来看看@Bean标记的方法如何转换为beanDefinition对象。从这部分代码可以看出,通过@Bean标识的方法对应的beanDefinition对象的实例化是通过工厂方法(FactoryMethod)实现的。(代码A)

      1. private void loadBeanDefinitionsForBeanMethod(BeanMethod beanMethod) {
      2. // 配置类
      3. ConfigurationClass configClass = beanMethod.getConfigurationClass();
      4. // 获取方法的元数据
      5. MethodMetadata metadata = beanMethod.getMetadata();
      6. // 获取方法名称
      7. String methodName = metadata.getMethodName();
      8. // Do we need to mark the bean as skipped by its condition?
      9. if (this.conditionEvaluator.shouldSkip(metadata, ConfigurationPhase.REGISTER_BEAN)) {
      10. configClass.skippedBeanMethods.add(methodName);
      11. return;
      12. }
      13. if (configClass.skippedBeanMethods.contains(methodName)) {
      14. return;
      15. }
      16. // 获取@Bean注解信息
      17. AnnotationAttributes bean = AnnotationConfigUtils.attributesFor(metadata, Bean.class);
      18. Assert.state(bean != null, "No @Bean annotation attributes");
      19. // Consider name and any aliases
      20. // @Bean(name = {"beanName","aliasFirst","aliasSecond"})
      21. List names = new ArrayList<>(Arrays.asList(bean.getStringArray("name")));
      22. // 默认第一个元素为beanName
      23. String beanName = (!names.isEmpty() ? names.remove(0) : methodName);
      24. // Register aliases even when overridden
      25. for (String alias : names) {
      26. // 设置别名
      27. this.registry.registerAlias(beanName, alias);
      28. }
      29. // Has this effectively been overridden before (e.g. via XML)?
      30. if (isOverriddenByExistingDefinition(beanMethod, beanName)) {
      31. if (beanName.equals(beanMethod.getConfigurationClass().getBeanName())) {
      32. throw new BeanDefinitionStoreException(beanMethod.getConfigurationClass().getResource().getDescription(),
      33. beanName, "Bean name derived from @Bean method '" + beanMethod.getMetadata().getMethodName() +
      34. "' clashes with bean name for containing configuration class; please make those names unique!");
      35. }
      36. return;
      37. }
      38. ConfigurationClassBeanDefinition beanDef = new ConfigurationClassBeanDefinition(configClass, metadata, beanName);
      39. // 如果Source中有占位符或其他特殊符号,使用相关解析器进行解析
      40. beanDef.setSource(this.sourceExtractor.extractSource(metadata, configClass.getResource()));
      41. if (metadata.isStatic()) {
      42. // static @Bean method
      43. if (configClass.getMetadata() instanceof StandardAnnotationMetadata) {
      44. beanDef.setBeanClass(((StandardAnnotationMetadata) configClass.getMetadata()).getIntrospectedClass());
      45. }
      46. else {
      47. //静态工厂方法创建的需要设置beanClassName
      48. beanDef.setBeanClassName(configClass.getMetadata().getClassName());
      49. }
      50. // 设置创建实例的FactoryMethodName
      51. beanDef.setUniqueFactoryMethodName(methodName);
      52. }
      53. else {
      54. // instance @Bean method
      55. // 如果是实例工厂方法,需要设置factoryBeanName
      56. beanDef.setFactoryBeanName(configClass.getBeanName());
      57. // 设置创建实例的FactoryMethodName
      58. beanDef.setUniqueFactoryMethodName(methodName);
      59. }
      60. if (metadata instanceof StandardMethodMetadata) {
      61. beanDef.setResolvedFactoryMethod(((StandardMethodMetadata) metadata).getIntrospectedMethod());
      62. }
      63. // 由于FactoryMethod方式实例化对象最后也是调用构造器完成对象实例化的,所以自动装配的方式也为通过构造器注入
      64. beanDef.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_CONSTRUCTOR);
      65. beanDef.setAttribute(org.springframework.beans.factory.annotation.RequiredAnnotationBeanPostProcessor.
      66. SKIP_REQUIRED_CHECK_ATTRIBUTE, Boolean.TRUE);
      67. AnnotationConfigUtils.processCommonDefinitionAnnotations(beanDef, metadata);
      68. /**
      69. * 根据注解的相关信息设置beanDefinition的相关属性值
      70. **/
      71. // 如果注解指定了自动装配方式,使用指定的自动注入方式
      72. Autowire autowire = bean.getEnum("autowire");
      73. if (autowire.isAutowire()) {
      74. beanDef.setAutowireMode(autowire.value());
      75. }
      76. boolean autowireCandidate = bean.getBoolean("autowireCandidate");
      77. if (!autowireCandidate) {
      78. beanDef.setAutowireCandidate(false);
      79. }
      80. String initMethodName = bean.getString("initMethod");
      81. if (StringUtils.hasText(initMethodName)) {
      82. beanDef.setInitMethodName(initMethodName);
      83. }
      84. String destroyMethodName = bean.getString("destroyMethod");
      85. beanDef.setDestroyMethodName(destroyMethodName);
      86. // Consider scoping
      87. ScopedProxyMode proxyMode = ScopedProxyMode.NO;
      88. AnnotationAttributes attributes = AnnotationConfigUtils.attributesFor(metadata, Scope.class);
      89. if (attributes != null) {
      90. beanDef.setScope(attributes.getString("value"));
      91. proxyMode = attributes.getEnum("proxyMode");
      92. if (proxyMode == ScopedProxyMode.DEFAULT) {
      93. proxyMode = ScopedProxyMode.NO;
      94. }
      95. }
      96. // Replace the original bean definition with the target one, if necessary
      97. BeanDefinition beanDefToRegister = beanDef;
      98. if (proxyMode != ScopedProxyMode.NO) {
      99. BeanDefinitionHolder proxyDef = ScopedProxyCreator.createScopedProxy(
      100. new BeanDefinitionHolder(beanDef, beanName), this.registry,
      101. proxyMode == ScopedProxyMode.TARGET_CLASS);
      102. beanDefToRegister = new ConfigurationClassBeanDefinition(
      103. (RootBeanDefinition) proxyDef.getBeanDefinition(), configClass, metadata, beanName);
      104. }
      105. if (logger.isTraceEnabled()) {
      106. logger.trace(String.format("Registering bean definition for @Bean method %s.%s()",
      107. configClass.getMetadata().getClassName(), beanName));
      108. }
      109. // 将封装好的beanDefinition注册到容器中
      110. this.registry.registerBeanDefinition(beanName, beanDefToRegister);
      111. }

              这里遍历步骤4(代码十九)中的Map,执行ImportBeanDefinitionRegistrar对象的registerBeanDefinitions()方法。(代码B)

      1. private void loadBeanDefinitionsFromRegistrars(Map registrars) {
      2. // 遍历this.importBeanDefinitionRegistrars中的对象,执行其registerBeanDefinitions()方法
      3. registrars.forEach((registrar, metadata) ->
      4. registrar.registerBeanDefinitions(metadata, this.registry, this.importBeanNameGenerator));
      5. }

              至此,执行完了 processConfigBeanDefinitions()方法的流程,完成了配置类的扫描解析。

      四、Mybatis对ImportBeanDefinitionRegistrar的扩展

              我们看看Mybatis核心注解@MapperScan,可以看到其通过@Import()引入了MapperScannerRegistrar.class

      1. @Retention(RetentionPolicy.RUNTIME)
      2. @Target(ElementType.TYPE)
      3. @Documented
      4. @Import(MapperScannerRegistrar.class)
      5. @Repeatable(MapperScans.class)
      6. public @interface MapperScan {
      7. ……
      8. }

      (1)老版本Mybatis的MapperScannerRegistrar

      1. public class MapperScannerRegistrar implements ImportBeanDefinitionRegistrar, ResourceLoaderAware {
      2. ……
      3. //ImportBeanDefinitionRegistrar的接口方法
      4. //老版的mybatis在这个方法中创建了scanner完成扫描
      5. @Override
      6. public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
      7. AnnotationAttributes annoAttrs = AnnotationAttributes.fromMap(importingClassMetadata.getAnnotationAttributes(MapperScan.class.getName()));
      8. ClassPathMapperScanner scanner = new ClassPathMapperScanner(registry);
      9. ……
      10. scanner.registerFilters();
      11. scanner.doScan(StringUtils.toStringArray(basePackages));
      12. }

      (2)新版本Mybatis的MapperScannerRegister

              新版的Mybatis的实现。新版的mybatis在registerBeanDefinitions()方法中创建了BeanDefinitionRegistryPostProcessor类型的对象MapperScannerConfigurer.

      1. public class MapperScannerRegistrar implements ImportBeanDefinitionRegistrar, ResourceLoaderAware {
      2. public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
      3. AnnotationAttributes mapperScanAttrs = AnnotationAttributes
      4. .fromMap(importingClassMetadata.getAnnotationAttributes(MapperScan.class.getName()));
      5. if (mapperScanAttrs != null) {
      6. registerBeanDefinitions(importingClassMetadata, mapperScanAttrs, registry,
      7. generateBaseBeanName(importingClassMetadata, 0));
      8. }
      9. }
      10. void registerBeanDefinitions(AnnotationMetadata annoMeta, AnnotationAttributes annoAttrs,
      11. BeanDefinitionRegistry registry, String beanName) {
      12. BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(MapperScannerConfigurer.class);
      13. ……
      14. }

              在 MapperScannerConfigurer类实现的BeanDefinitionRegistryPostProcessor接口方法中创建扫描器,完成自定义注解的扫描解析。

      1. public class MapperScannerConfigurer
      2. implements BeanDefinitionRegistryPostProcessor, InitializingBean, ApplicationContextAware, BeanNameAware {
      3. ……
      4. @Override
      5. public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
      6. if (this.processPropertyPlaceHolders) {
      7. processPropertyPlaceHolders();
      8. }
      9. ClassPathMapperScanner scanner = new ClassPathMapperScanner(registry);
      10. scanner.setAddToConfig(this.addToConfig);
      11. scanner.setAnnotationClass(this.annotationClass);
      12. scanner.setMarkerInterface(this.markerInterface);
      13. scanner.setSqlSessionFactory(this.sqlSessionFactory);
      14. scanner.setSqlSessionTemplate(this.sqlSessionTemplate);
      15. scanner.setSqlSessionFactoryBeanName(this.sqlSessionFactoryBeanName);
      16. scanner.setSqlSessionTemplateBeanName(this.sqlSessionTemplateBeanName);
      17. scanner.setResourceLoader(this.applicationContext);
      18. scanner.setBeanNameGenerator(this.nameGenerator);
      19. scanner.setMapperFactoryBeanClass(this.mapperFactoryBeanClass);
      20. if (StringUtils.hasText(lazyInitialization)) {
      21. scanner.setLazyInitialization(Boolean.valueOf(lazyInitialization));
      22. }
      23. scanner.registerFilters();
      24. scanner.scan(
      25. StringUtils.tokenizeToStringArray(this.basePackage, ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS));
      26. }
      27. ……
      28. }

      (3)新版和老版的mybatis的区别

      • ​老版的mybatis扫描的入口是@MapperScan的ImportBeanDefinitionRegistrar,如果不加@MapperScan,mybatis无法完成扫描。新版的mybatis可以不加@MapperScan,而是通过向spring容器中注入MapperScannerConfigurer即可完成扫描。
      • 执行时机不同,老版扫描发生在ConfigurationClassPostProcessor进行扫描解析配置类时。新版的执行时机要晚一些,新版的扫描在执行普通的BeanDefinitionRegistryPostProcessor类(没有实现PriorityOrdered和Order接口)的接口方法时完成的。

      五、总结

              通过上述的源码分析,我们可以发现不同类型的BeanDefinitionRegistryPostProcessor和BeanFactoryPostProcessor的执行时机(执行顺序)。同时对Spring核心类ConfigurationClassPostProcessor进行源码分析时,发现它的功能非常强大,其中包括:

              1.加载配置文件(解析@PropertySource和@ImportResource 注解的相关属性信息,完成配置文件的加载。)

              2.扫描解析@Component注解,将符合条件的组件创建为beanBefinition。(扩展点:自定义扫描器如何工作?Mybatis为什么能扫描接口类?后续详细展开)

              3.对@Import注解导入的核心接口ImportBeanDefinitionRegistrar的处理。(扩展点:Mybatis注解扫描的时机?)

              4.将@Bean标识得方法转换成对应的beanDefinition。

              5.生成CGLIB代理对象。(BeanFactoryPostProcessor接口方法实现的功能,后续详细展开)


            

    16. 相关阅读:
      Linux tee 笔记221108
      物联网开发笔记(5)- 使用Wokwi仿真树莓派Pico实现LED灯交替闪烁(续)
      论文阅读笔记——A deep tree-based model for software defect prediction
      英文翻译法语-英文法语翻译软件
      vue js中使用typeof和Object.prototype.toString.call()判断类型(超详细),浅析call()和apply()的区别
      stc8a8k64s4a12单片机声音检测编程
      华为HCIE云计算之ebackup备份FC虚拟机
      PHP 图书资料管理系统mysql数据库web结构apache计算机软件工程网页wamp
      CC26XX睡眠
      数据库优化redis【培训结语】
    17. 原文地址:https://blog.csdn.net/ZHANGLI_WORB/article/details/133832162