原创-spring源码-@Configuration和@ComponentScan解析原理
spring容器启动的核心refresh方法我相信大家都不陌生,其中invokeBeanFactoryPostProcessors方法是处理beanFactory的一个非常重要的方法,@Component @Bean等等都是在该方法里实现解析的。
1 @Configuration 2 @ComponentScan("org.springframework.context.annotation") 3 public class MyComponentScan { 4 @ComponentScan("org.springframework.context.annotation") 5 @Configuration 6 class InnerClass{ 7 } 8 }
下面以MyComponentScan 为例debug进入invokeBeanFactoryPostProcessors方法。
1 @Override 2 public void refresh() throws BeansException, IllegalStateException { 3 synchronized (this.startupShutdownMonitor) { 4 // Prepare this context for refreshing. 5 prepareRefresh(); 6 7 // Tell the subclass to refresh the internal bean factory. 8 // 创建容器对象:DefaultListableBeanFactory 9 // 加载xml配置文件的属性值到当前工厂中,最重要的就是BeanDefinition 10 ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); 11 12 // Prepare the bean factory for use in this context. 13 // beanFactory的准备工作,对各种属性进行填充 14 prepareBeanFactory(beanFactory); 15 16 try { 17 // Allows post-processing of the bean factory in context subclasses. 18 // 子类覆盖方法做额外的处理,此处我们自己一般不做任何扩展工作,但是可以查看web中的代码,是有具体实现的 19 postProcessBeanFactory(beanFactory); 20 21 // Invoke factory processors registered as beans in the context. 22 // 调用各种beanFactory处理器 23 invokeBeanFactoryPostProcessors(beanFactory); 24 25 // Register bean processors that intercept bean creation. 26 // 注册bean处理器,这里只是注册功能,真正调用的是getBean方法 27 registerBeanPostProcessors(beanFactory); 28 29 // Initialize message source for this context. 30 // 为上下文初始化message源,即不同语言的消息体,国际化处理,在springmvc的时候通过国际化的代码重点讲 31 initMessageSource(); 32 33 // Initialize event multicaster for this context. 34 // 初始化事件监听多路广播器 35 initApplicationEventMulticaster(); 36 37 // Initialize other special beans in specific context subclasses. 38 // 留给子类来初始化其他的bean 39 onRefresh(); 40 41 // Check for listener beans and register them. 42 // 在所有注册的bean中查找listener bean,注册到消息广播器中 43 registerListeners(); 44 45 // Instantiate all remaining (non-lazy-init) singletons. 46 // 初始化剩下的单实例(非懒加载的) 47 finishBeanFactoryInitialization(beanFactory); 48 49 // Last step: publish corresponding event. 50 // 完成刷新过程,通知生命周期处理器lifecycleProcessor刷新过程,同时发出ContextRefreshEvent通知别人 51 finishRefresh(); 52 } 53 54 catch (BeansException ex) { 55 if (logger.isWarnEnabled()) { 56 logger.warn("Exception encountered during context initialization - " + 57 "cancelling refresh attempt: " + ex); 58 } 59 60 // Destroy already created singletons to avoid dangling resources. 61 // 为防止bean资源占用,在异常处理中,销毁已经在前面过程中生成的单件bean 62 destroyBeans(); 63 64 // Reset 'active' flag. 65 // 重置active标志 66 cancelRefresh(ex); 67 68 // Propagate exception to caller. 69 throw ex; 70 } 71 72 finally { 73 // Reset common introspection caches in Spring's core, since we 74 // might not ever need metadata for singleton beans anymore... 75 resetCommonCaches(); 76 } 77 } 78 }
这个方法里面就不得不提到一个接口-BeanFactoryPostProcessor,BeanFactoryPostProcessor作为一个后置处理器,主要用来处理BeanFactory的一些信息,但是如果只有BeanFactoryPostProcessor的话,就需要在BeanFactoryPostProcessor的方法里定义对各种对象的相关操作,而BeanDefinition(还没实例化之前,配置文件定义的对象加载到spring容器中的一种表现形式)是比较核心比较关键的点,所以把这个东西抽象一层,做了一个子类BeanDefinitionRegistryPostProcessor专门对BeanDefinition进行增删改查操作。我们这里解析这些注解,就要用到BeanDefinitionRegistryPostProcessor类的实现类ConfigurationClassPostProcessor类了。如下代码所示,在遍历循环众多的BeanFactoryPostProcessor中,我们重点看第64行的处理环节
1 public static void invokeBeanFactoryPostProcessors( 2 ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) { 3 4 // Invoke BeanDefinitionRegistryPostProcessors first, if any. 5 // 无论是什么情况,优先执行BeanDefinitionRegistryPostProcessors 6 // 将已经执行过的BFPP存储在processedBeans中,防止重复执行 7 Set<String> processedBeans = new HashSet<>(); 8 9 // 判断beanfactory是否是BeanDefinitionRegistry类型,此处是DefaultListableBeanFactory,实现了BeanDefinitionRegistry接口,所以为true 10 if (beanFactory instanceof BeanDefinitionRegistry) { 11 // 类型转换 12 BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory; 13 // 此处希望大家做一个区分,两个接口是不同的,BeanDefinitionRegistryPostProcessor是BeanFactoryPostProcessor的子集 14 // BeanFactoryPostProcessor主要针对的操作对象是BeanFactory,而BeanDefinitionRegistryPostProcessor主要针对的操作对象是BeanDefinition 15 // 存放BeanFactoryPostProcessor的集合 16 List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>(); 17 // 存放BeanDefinitionRegistryPostProcessor的集合 18 List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>(); 19 20 // 首先处理入参中的beanFactoryPostProcessors,遍历所有的beanFactoryPostProcessors,将BeanDefinitionRegistryPostProcessor 21 // 和BeanFactoryPostProcessor区分开 22 for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) { 23 // 如果是BeanDefinitionRegistryPostProcessor 24 if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) { 25 BeanDefinitionRegistryPostProcessor registryProcessor = 26 (BeanDefinitionRegistryPostProcessor) postProcessor; 27 // 直接执行BeanDefinitionRegistryPostProcessor接口中的postProcessBeanDefinitionRegistry方法 28 registryProcessor.postProcessBeanDefinitionRegistry(registry); 29 // 添加到registryProcessors,用于后续执行postProcessBeanFactory方法 30 registryProcessors.add(registryProcessor); 31 } else { 32 // 否则,只是普通的BeanFactoryPostProcessor,添加到regularPostProcessors,用于后续执行postProcessBeanFactory方法 33 regularPostProcessors.add(postProcessor); 34 } 35 } 36 37 // Do not initialize FactoryBeans here: We need to leave all regular beans 38 // uninitialized to let the bean factory post-processors apply to them! 39 // Separate between BeanDefinitionRegistryPostProcessors that implement 40 // PriorityOrdered, Ordered, and the rest. 41 // 用于保存本次要执行的BeanDefinitionRegistryPostProcessor 42 List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>(); 43 44 // First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered. 45 // 调用所有实现PriorityOrdered接口的BeanDefinitionRegistryPostProcessor实现类 46 // 找到所有实现BeanDefinitionRegistryPostProcessor接口bean的beanName 47 String[] postProcessorNames = 48 beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false); 49 // 遍历处理所有符合规则的postProcessorNames 50 for (String ppName : postProcessorNames) { 51 // 检测是否实现了PriorityOrdered接口 52 if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) { 53 // 获取名字对应的bean实例,添加到currentRegistryProcessors中 54 currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class)); 55 // 将要被执行的BFPP名称添加到processedBeans,避免后续重复执行 56 processedBeans.add(ppName); 57 } 58 } 59 // 按照优先级进行排序操作 60 sortPostProcessors(currentRegistryProcessors, beanFactory); 61 // 添加到registryProcessors中,用于最后执行postProcessBeanFactory方法 62 registryProcessors.addAll(currentRegistryProcessors); 63 // 遍历currentRegistryProcessors,执行postProcessBeanDefinitionRegistry方法 64 invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry); 65 // 执行完毕之后,清空currentRegistryProcessors 66 currentRegistryProcessors.clear(); 67 68 // Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered. 69 // 调用所有实现Ordered接口的BeanDefinitionRegistryPostProcessor实现类 70 // 找到所有实现BeanDefinitionRegistryPostProcessor接口bean的beanName, 71 // 此处需要重复查找的原因在于上面的执行过程中可能会新增其他的BeanDefinitionRegistryPostProcessor 72 postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false); 73 for (String ppName : postProcessorNames) { 74 // 检测是否实现了Ordered接口,并且还未执行过 75 if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) { 76 // 获取名字对应的bean实例,添加到currentRegistryProcessors中 77 currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class)); 78 // 将要被执行的BFPP名称添加到processedBeans,避免后续重复执行 79 processedBeans.add(ppName); 80 } 81 } 82 // 按照优先级进行排序操作 83 sortPostProcessors(currentRegistryProcessors, beanFactory); 84 // 添加到registryProcessors中,用于最后执行postProcessBeanFactory方法 85 registryProcessors.addAll(currentRegistryProcessors); 86 // 遍历currentRegistryProcessors,执行postProcessBeanDefinitionRegistry方法 87 invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry); 88 // 执行完毕之后,清空currentRegistryProcessors 89 currentRegistryProcessors.clear(); 90 91 // Finally, invoke all other BeanDefinitionRegistryPostProcessors until no further ones appear. 92 // 最后,调用所有剩下的BeanDefinitionRegistryPostProcessors 93 boolean reiterate = true; 94 while (reiterate) { 95 reiterate = false; 96 // 找出所有实现BeanDefinitionRegistryPostProcessor接口的类 97 postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false); 98 // 遍历执行 99 for (String ppName : postProcessorNames) { 100 // 跳过已经执行过的BeanDefinitionRegistryPostProcessor 101 if (!processedBeans.contains(ppName)) { 102 // 获取名字对应的bean实例,添加到currentRegistryProcessors中 103 currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class)); 104 // 将要被执行的BFPP名称添加到processedBeans,避免后续重复执行 105 processedBeans.add(ppName); 106 reiterate = true; 107 } 108 } 109 // 按照优先级进行排序操作 110 sortPostProcessors(currentRegistryProcessors, beanFactory); 111 // 添加到registryProcessors中,用于最后执行postProcessBeanFactory方法 112 registryProcessors.addAll(currentRegistryProcessors); 113 // 遍历currentRegistryProcessors,执行postProcessBeanDefinitionRegistry方法 114 invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry); 115 // 执行完毕之后,清空currentRegistryProcessors 116 currentRegistryProcessors.clear(); 117 } 118 119 // Now, invoke the postProcessBeanFactory callback of all processors handled so far. 120 // 调用所有BeanDefinitionRegistryPostProcessor的postProcessBeanFactory方法 121 invokeBeanFactoryPostProcessors(registryProcessors, beanFactory); 122 // 最后,调用入参beanFactoryPostProcessors中的普通BeanFactoryPostProcessor的postProcessBeanFactory方法 123 invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory); 124 } else { 125 // Invoke factory processors registered with the context instance. 126 // 如果beanFactory不归属于BeanDefinitionRegistry类型,那么直接执行postProcessBeanFactory方法 127 invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory); 128 } 129 130 // 到这里为止,入参beanFactoryPostProcessors和容器中的所有BeanDefinitionRegistryPostProcessor已经全部处理完毕,下面开始处理容器中 131 // 所有的BeanFactoryPostProcessor 132 // 可能会包含一些实现类,只实现了BeanFactoryPostProcessor,并没有实现BeanDefinitionRegistryPostProcessor接口 133 134 // Do not initialize FactoryBeans here: We need to leave all regular beans 135 // uninitialized to let the bean factory post-processors apply to them! 136 // 找到所有实现BeanFactoryPostProcessor接口的类 137 String[] postProcessorNames = 138 beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false); 139 140 // Separate between BeanFactoryPostProcessors that implement PriorityOrdered, 141 // Ordered, and the rest. 142 // 用于存放实现了PriorityOrdered接口的BeanFactoryPostProcessor 143 List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<>(); 144 // 用于存放实现了Ordered接口的BeanFactoryPostProcessor的beanName 145 // List<String> orderedPostProcessorNames = new ArrayList<>(); 146 List<BeanFactoryPostProcessor> orderedPostProcessor = new ArrayList<>(); 147 // 用于存放普通BeanFactoryPostProcessor的beanName 148 // List<String> nonOrderedPostProcessorNames = new ArrayList<>(); 149 List<BeanFactoryPostProcessor> nonOrderedPostProcessorNames = new ArrayList<>(); 150 // 遍历postProcessorNames,将BeanFactoryPostProcessor按实现PriorityOrdered、实现Ordered接口、普通三种区分开 151 for (String ppName : postProcessorNames) { 152 // 跳过已经执行过的BeanFactoryPostProcessor 153 if (processedBeans.contains(ppName)) { 154 // skip - already processed in first phase above 155 } 156 // 添加实现了PriorityOrdered接口的BeanFactoryPostProcessor到priorityOrderedPostProcessors 157 else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) { 158 priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class)); 159 } 160 // 添加实现了Ordered接口的BeanFactoryPostProcessor的beanName到orderedPostProcessorNames 161 else if (beanFactory.isTypeMatch(ppName, Ordered.class)) { 162 // orderedPostProcessorNames.add(ppName); 163 orderedPostProcessor.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class)); 164 } else { 165 // 添加剩下的普通BeanFactoryPostProcessor的beanName到nonOrderedPostProcessorNames 166 // nonOrderedPostProcessorNames.add(ppName); 167 nonOrderedPostProcessorNames.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class)); 168 } 169 } 170 171 // First, invoke the BeanFactoryPostProcessors that implement PriorityOrdered. 172 // 对实现了PriorityOrdered接口的BeanFactoryPostProcessor进行排序 173 sortPostProcessors(priorityOrderedPostProcessors, beanFactory); 174 // 遍历实现了PriorityOrdered接口的BeanFactoryPostProcessor,执行postProcessBeanFactory方法 175 invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory); 176 177 // Next, invoke the BeanFactoryPostProcessors that implement Ordered. 178 // 创建存放实现了Ordered接口的BeanFactoryPostProcessor集合 179 // List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size()); 180 // 遍历存放实现了Ordered接口的BeanFactoryPostProcessor名字的集合 181 // for (String postProcessorName : orderedPostProcessorNames) { 182 // 将实现了Ordered接口的BeanFactoryPostProcessor添加到集合中 183 // orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class)); 184 // } 185 // 对实现了Ordered接口的BeanFactoryPostProcessor进行排序操作 186 // sortPostProcessors(orderedPostProcessors, beanFactory); 187 sortPostProcessors(orderedPostProcessor, beanFactory); 188 // 遍历实现了Ordered接口的BeanFactoryPostProcessor,执行postProcessBeanFactory方法 189 // invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory); 190 invokeBeanFactoryPostProcessors(orderedPostProcessor, beanFactory); 191 192 // Finally, invoke all other BeanFactoryPostProcessors. 193 // 最后,创建存放普通的BeanFactoryPostProcessor的集合 194 // List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size()); 195 // 遍历存放实现了普通BeanFactoryPostProcessor名字的集合 196 // for (String postProcessorName : nonOrderedPostProcessorNames) { 197 // 将普通的BeanFactoryPostProcessor添加到集合中 198 // nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class)); 199 // } 200 // 遍历普通的BeanFactoryPostProcessor,执行postProcessBeanFactory方法 201 // invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory); 202 invokeBeanFactoryPostProcessors(nonOrderedPostProcessorNames, beanFactory); 203 204 // Clear cached merged bean definitions since the post-processors might have 205 // modified the original metadata, e.g. replacing placeholders in values... 206 // 清除元数据缓存(mergeBeanDefinitions、allBeanNamesByType、singletonBeanNameByType) 207 // 因为后置处理器可能已经修改了原始元数据,例如,替换值中的占位符 208 beanFactory.clearMetadataCache(); 209 }
进入第12行的处理环节
1 /** 2 * 调用给定 BeanDefinitionRegistryPostProcessor Bean对象 3 * 4 * Invoke the given BeanDefinitionRegistryPostProcessor beans. 5 */ 6 private static void invokeBeanDefinitionRegistryPostProcessors( 7 Collection<? extends BeanDefinitionRegistryPostProcessor> postProcessors, BeanDefinitionRegistry registry) { 8 9 //遍历 postProcessors 10 for (BeanDefinitionRegistryPostProcessor postProcessor : postProcessors) { 11 //调用 postProcessor 的 postProcessBeanDefinitionRegistry以使得postProcess往registry注册BeanDefinition对象 12 postProcessor.postProcessBeanDefinitionRegistry(registry); 13 } 14 }
进入第22行的处理环节
1 /** 2 * 定位、加载、解析、注册相关注解 3 * 4 * Derive further bean definitions from the configuration classes in the registry. 5 */ 6 @Override 7 public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) { 8 // 根据对应的registry对象生成hashcode值,此对象只会操作一次,如果之前处理过则抛出异常 9 int registryId = System.identityHashCode(registry); 10 if (this.registriesPostProcessed.contains(registryId)) { 11 throw new IllegalStateException( 12 "postProcessBeanDefinitionRegistry already called on this post-processor against " + registry); 13 } 14 if (this.factoriesPostProcessed.contains(registryId)) { 15 throw new IllegalStateException( 16 "postProcessBeanFactory already called on this post-processor against " + registry); 17 } 18 // 将马上要进行处理的registry对象的id值放到已经处理的集合对象中 19 this.registriesPostProcessed.add(registryId); 20 21 // 处理配置类的bean定义信息 22 processConfigBeanDefinitions(registry); 23 }
如下方法是核心处理环节,BeanDefinitionHolder是BeanDefinition的包装类,既包括BeanDefinition、beanName以及别名,配置文件加载后所有东西都会放到BeanDefinitionMap和BeanDefinitionNames中,BeanDefinitionNames放的是name集合,BeanDefinitionMap放的是name和完整的BeanDefinition对象的KV键值对集合,在这里取出所有的name集合。
循环只做了一件事,将被某些注解所修饰的BeanDefinition筛选出来。
获取BeanDefinition,判断BeanDefinition是否包含CONFIGURATION_CLASS_ATTRIBUTE属性值(),不包含,126行工具类进去。
1 /** 2 * 构建和验证一个类是否被@Configuration修饰,并做相关的解析工作 3 * 4 * 如果你对此方法了解清楚了,那么springboot的自动装配原理就清楚了 5 * 6 * Build and validate a configuration model based on the registry of 7 * {@link Configuration} classes. 8 */ 9 public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) { 10 // 创建存放BeanDefinitionHolder的对象集合 11 List<BeanDefinitionHolder> configCandidates = new ArrayList<>(); 12 // 当前registry就是DefaultListableBeanFactory,获取所有已经注册的BeanDefinition的beanName 13 String[] candidateNames = registry.getBeanDefinitionNames(); 14 15 // 遍历所有要处理的beanDefinition的名称,筛选对应的beanDefinition(被注解修饰的) 16 for (String beanName : candidateNames) { 17 // 获取指定名称的BeanDefinition对象 18 BeanDefinition beanDef = registry.getBeanDefinition(beanName); 19 // 如果beanDefinition中的configurationClass属性不等于空,那么意味着已经处理过,输出日志信息 20 if (beanDef.getAttribute(ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTE) != null) { 21 if (logger.isDebugEnabled()) { 22 logger.debug("Bean definition has already been processed as a configuration class: " + beanDef); 23 } 24 } 25 // 判断当前BeanDefinition是否是一个配置类,并为BeanDefinition设置属性为lite或者full,此处设置属性值是为了后续进行调用 26 // 如果Configuration配置proxyBeanMethods代理为true则为full 27 // 如果加了@Bean、@Component、@ComponentScan、@Import、@ImportResource注解,则设置为lite 28 // 如果配置类上被@Order注解标注,则设置BeanDefinition的order属性值 29 else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) { 30 // 添加到对应的集合对象中 31 configCandidates.add(new BeanDefinitionHolder(beanDef, beanName)); 32 } 33 } 34 35 // Return immediately if no @Configuration classes were found 36 // 如果没有发现任何配置类,则直接返回 37 if (configCandidates.isEmpty()) { 38 return; 39 } 40 41 // Sort by previously determined @Order value, if applicable 42 // 如果适用,则按照先前确定的@Order的值排序 43 configCandidates.sort((bd1, bd2) -> { 44 int i1 = ConfigurationClassUtils.getOrder(bd1.getBeanDefinition()); 45 int i2 = ConfigurationClassUtils.getOrder(bd2.getBeanDefinition()); 46 return Integer.compare(i1, i2); 47 }); 48 49 // Detect any custom bean name generation strategy supplied through the enclosing application context 50 // 判断当前类型是否是SingletonBeanRegistry类型 51 SingletonBeanRegistry sbr = null; 52 if (registry instanceof SingletonBeanRegistry) { 53 // 类型的强制转换 54 sbr = (SingletonBeanRegistry) registry; 55 // 判断是否有自定义的beanName生成器 56 if (!this.localBeanNameGeneratorSet) { 57 // 获取自定义的beanName生成器 58 BeanNameGenerator generator = (BeanNameGenerator) sbr.getSingleton( 59 AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR); 60 // 如果有自定义的命名生成策略 61 if (generator != null) { 62 //设置组件扫描的beanName生成策略 63 this.componentScanBeanNameGenerator = generator; 64 // 设置import bean name生成策略 65 this.importBeanNameGenerator = generator; 66 } 67 } 68 } 69 70 // 如果环境对象等于空,那么就重新创建新的环境对象 71 if (this.environment == null) { 72 this.environment = new StandardEnvironment(); 73 } 74 75 // Parse each @Configuration class 76 // 实例化ConfigurationClassParser类,并初始化相关的参数,完成配置类的解析工作 77 ConfigurationClassParser parser = new ConfigurationClassParser( 78 this.metadataReaderFactory, this.problemReporter, this.environment, 79 this.resourceLoader, this.componentScanBeanNameGenerator, registry); 80 81 // 创建两个集合对象, 82 // 存放相关的BeanDefinitionHolder对象 83 Set<BeanDefinitionHolder> candidates = new LinkedHashSet<>(configCandidates); 84 // 存放扫描包下的所有bean 85 Set<ConfigurationClass> alreadyParsed = new HashSet<>(configCandidates.size()); 86 do { 87 // 解析带有@Controller、@Import、@ImportResource、@ComponentScan、@ComponentScans、@Bean的BeanDefinition 88 parser.parse(candidates); 89 // 将解析完的Configuration配置类进行校验,1、配置类不能是final,2、@Bean修饰的方法必须可以重写以支持CGLIB 90 parser.validate(); 91 92 // 获取所有的bean,包括扫描的bean对象,@Import导入的bean对象 93 Set<ConfigurationClass> configClasses = new LinkedHashSet<>(parser.getConfigurationClasses()); 94 // 清除掉已经解析处理过的配置类 95 configClasses.removeAll(alreadyParsed); 96 97 // Read the model and create bean definitions based on its content 98 // 判断读取器是否为空,如果为空的话,就创建完全填充好的ConfigurationClass实例的读取器 99 if (this.reader == null) { 100 this.reader = new ConfigurationClassBeanDefinitionReader( 101 registry, this.sourceExtractor, this.resourceLoader, this.environment, 102 this.importBeanNameGenerator, parser.getImportRegistry()); 103 } 104 // 核心方法,将完全填充好的ConfigurationClass实例转化为BeanDefinition注册入IOC容器 105 this.reader.loadBeanDefinitions(configClasses); 106 // 添加到已经处理的集合中 107 alreadyParsed.addAll(configClasses); 108 109 candidates.clear(); 110 // 这里判断registry.getBeanDefinitionCount() > candidateNames.length的目的是为了知道reader.loadBeanDefinitions(configClasses)这一步有没有向BeanDefinitionMap中添加新的BeanDefinition 111 // 实际上就是看配置类(例如AppConfig类会向BeanDefinitionMap中添加bean) 112 // 如果有,registry.getBeanDefinitionCount()就会大于candidateNames.length 113 // 这样就需要再次遍历新加入的BeanDefinition,并判断这些bean是否已经被解析过了,如果未解析,需要重新进行解析 114 // 这里的AppConfig类向容器中添加的bean,实际上在parser.parse()这一步已经全部被解析了 115 if (registry.getBeanDefinitionCount() > candidateNames.length) { 116 String[] newCandidateNames = registry.getBeanDefinitionNames(); 117 Set<String> oldCandidateNames = new HashSet<>(Arrays.asList(candidateNames)); 118 Set<String> alreadyParsedClasses = new HashSet<>(); 119 for (ConfigurationClass configurationClass : alreadyParsed) { 120 alreadyParsedClasses.add(configurationClass.getMetadata().getClassName()); 121 } 122 // 如果有未解析的类,则将其添加到candidates中,这样candidates不为空,就会进入到下一次的while的循环中 123 for (String candidateName : newCandidateNames) { 124 if (!oldCandidateNames.contains(candidateName)) { 125 BeanDefinition bd = registry.getBeanDefinition(candidateName); 126 if (ConfigurationClassUtils.checkConfigurationClassCandidate(bd, this.metadataReaderFactory) && 127 !alreadyParsedClasses.contains(bd.getBeanClassName())) { 128 candidates.add(new BeanDefinitionHolder(bd, candidateName)); 129 } 130 } 131 } 132 candidateNames = newCandidateNames; 133 } 134 } 135 while (!candidates.isEmpty()); 136 137 // Register the ImportRegistry as a bean in order to support ImportAware @Configuration classes 138 if (sbr != null && !sbr.containsSingleton(IMPORT_REGISTRY_BEAN_NAME)) { 139 sbr.registerSingleton(IMPORT_REGISTRY_BEAN_NAME, parser.getImportRegistry()); 140 } 141 142 if (this.metadataReaderFactory instanceof CachingMetadataReaderFactory) { 143 // Clear cache in externally provided MetadataReaderFactory; this is a no-op 144 // for a shared cache since it'll be cleared by the ApplicationContext. 145 ((CachingMetadataReaderFactory) this.metadataReaderFactory).clearCache(); 146 } 147 }
需要注意的是如果是从配置文件直接读的BeanDefinition,实现类是GenericBeanDefinition。而如果是以注解方式,实现类是ScannedGenericBeanDefinition,实现了AnnotatedBeanDefinition接口,其实就多了一个注解的相关元数据信息特殊处理。
1 public interface AnnotatedBeanDefinition extends BeanDefinition { 2 /** 3 * 获取注解的元数据 4 * 5 * Obtain the annotation metadata (as well as basic class metadata) 6 * for this bean definition's bean class. 7 * @return the annotation metadata object (never {@code null}) 8 */ 9 AnnotationMetadata getMetadata(); 10 /** 11 * 获取工厂方法的元数据 12 * 13 * Obtain metadata for this bean definition's factory method, if any. 14 * @return the factory method metadata, or {@code null} if none 15 * @since 4.1.1 16 */ 17 @Nullable 18 MethodMetadata getFactoryMethodMetadata(); 19 }
26行,不管三种方式匹配任何一个情况,最终目的都是为了获取AnnotatedMetadata对象,获取注解元数据信息后才知道当前BeanDefinition有什么样的注解。下面66行先判断是否是Configuration类,往下走isConfigurationCandidate里面判断是否含有其他注解,72行进去。
1 /** 2 * 检查当前给定的beanDefinition中是否是一个配置类的候选者, 3 * 判断在嵌套的关系中是否包含配置类或者组件类或者自动注册进去的,并做相应的标记 4 * 5 * Check whether the given bean definition is a candidate for a configuration class 6 * (or a nested component class declared within a configuration/component class, 7 * to be auto-registered as well), and mark it accordingly. 8 * @param beanDef the bean definition to check 9 * @param metadataReaderFactory the current factory in use by the caller 10 * @return whether the candidate qualifies as (any kind of) configuration class 11 */ 12 public static boolean checkConfigurationClassCandidate( 13 BeanDefinition beanDef, MetadataReaderFactory metadataReaderFactory) { 14 15 // 获取bean定义信息中的class类名 16 String className = beanDef.getBeanClassName(); 17 // 如果className为空,或者bean定义信息中的factoryMethod不等于空,那么直接返回 18 if (className == null || beanDef.getFactoryMethodName() != null) { 19 return false; 20 } 21 22 AnnotationMetadata metadata; 23 // 通过注解注入的db都是AnnotatedGenericBeanDefinition,实现了AnnotatedBeanDefinition 24 // spring内部的bd是RootBeanDefinition,实现了AbstractBeanDefinition 25 // 此处主要用于判断是否归属于AnnotatedBeanDefinition 26 if (beanDef instanceof AnnotatedBeanDefinition && 27 className.equals(((AnnotatedBeanDefinition) beanDef).getMetadata().getClassName())) { 28 // Can reuse the pre-parsed metadata from the given BeanDefinition... 29 // 从当前bean的定义信息中获取元数据信息 30 metadata = ((AnnotatedBeanDefinition) beanDef).getMetadata(); 31 } 32 // 判断是否是spring中默认的BeanDefinition 33 else if (beanDef instanceof AbstractBeanDefinition && ((AbstractBeanDefinition) beanDef).hasBeanClass()) { 34 // Check already loaded Class if present... 35 // since we possibly can't even load the class file for this Class. 36 // 获取当前bean对象的Class对象 37 Class<?> beanClass = ((AbstractBeanDefinition) beanDef).getBeanClass(); 38 // 如果class实例是下面四种类或接口的子类、父接口等任何一种情况,直接返回 39 if (BeanFactoryPostProcessor.class.isAssignableFrom(beanClass) || 40 BeanPostProcessor.class.isAssignableFrom(beanClass) || 41 AopInfrastructureBean.class.isAssignableFrom(beanClass) || 42 EventListenerFactory.class.isAssignableFrom(beanClass)) { 43 return false; 44 } 45 // 为给定类创建新的AnnotationMetadata实例 46 metadata = AnnotationMetadata.introspect(beanClass); 47 } 48 // 如果上述两种情况都不符合 49 else { 50 try { 51 // 获取className的MetadataReader实例 52 MetadataReader metadataReader = metadataReaderFactory.getMetadataReader(className); 53 // 读取底层类的完整注释元数据,包括带注解方法的元数据 54 metadata = metadataReader.getAnnotationMetadata(); 55 } 56 catch (IOException ex) { 57 if (logger.isDebugEnabled()) { 58 logger.debug("Could not find class file for introspecting configuration annotations: " + 59 className, ex); 60 } 61 return false; 62 } 63 } 64 65 // 获取bean定义的元数据被@Configuration注解标注的属性字典值 66 Map<String, Object> config = metadata.getAnnotationAttributes(Configuration.class.getName()); 67 // 如果bean被@Configuration注解标注,且属性proxyBeanMethods为false(使用代理模式),则将bean定义记为full 68 if (config != null && !Boolean.FALSE.equals(config.get("proxyBeanMethods"))) { 69 beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_FULL); 70 } 71 // 如果bean被@configuration注解标注,且被注解@Component,@ComponentScan、@Import、@ImportResource或者@Bean标记的方法,则将bean定义标记为lite 72 else if (config != null || isConfigurationCandidate(metadata)) { 73 beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_LITE); 74 } 75 else { 76 return false; 77 } 78 79 // It's a full or lite configuration candidate... Let's determine the order value, if any. 80 // bean定义是一个标记为full或lite的候选项,如果设置order则设置order属性值 81 Integer order = getOrder(metadata); 82 // 如果值不为空的话,那么直接设置值到具体的beanDefinition 83 if (order != null) { 84 // 设置bean定义的order值 85 beanDef.setAttribute(ORDER_ATTRIBUTE, order); 86 } 87 88 return true; 89 }
方法里面19行循环遍历集合,集合里面定义了4个注解:Component、ComponentScan、Import、ImportResource。如果都匹配不到,检查一下是否含有@Bean标注的方法
1 /** 2 * 检查给定的元数据,以查找给定的候选配置类是否被指定的注解标注 3 * 4 * Check the given metadata for a configuration class candidate 5 * (or nested component class declared within a configuration/component class). 6 * @param metadata the metadata of the annotated class 7 * @return {@code true} if the given class is to be registered for 8 * configuration class processing; {@code false} otherwise 9 */ 10 public static boolean isConfigurationCandidate(AnnotationMetadata metadata) { 11 // Do not consider an interface or an annotation... 12 // 不考虑接口或注解 13 if (metadata.isInterface()) { 14 return false; 15 } 16 17 // Any of the typical annotations found? 18 // 检查是否被注解@Component、@ComponentScan、@Import、@ImportResource标注 19 for (String indicator : candidateIndicators) { 20 if (metadata.isAnnotated(indicator)) { 21 return true; 22 } 23 } 24 25 // Finally, let's look for @Bean methods... 26 // 最后检查是否有@Bean标注的方法 27 try { 28 return metadata.hasAnnotatedMethods(Bean.class.getName()); 29 } 30 catch (Throwable ex) { 31 if (logger.isDebugEnabled()) { 32 logger.debug("Failed to introspect @Bean methods on class [" + metadata.getClassName() + "]: " + ex); 33 } 34 return false; 35 } 36 }
我们的MyComponentScan 包含@Component,所以73行加进来了,往当前BeanDefinition设置属性值key为configurationClass,属性值是LinkedHashMap结构,属性值的value为full或lite,当前注解是@Configuration标注的标注为full,非@Configuration标注的配置类标注为lite,最后返回true
1 /** 2 * 检查当前给定的beanDefinition中是否是一个配置类的候选者, 3 * 判断在嵌套的关系中是否包含配置类或者组件类或者自动注册进去的,并做相应的标记 4 * 5 * Check whether the given bean definition is a candidate for a configuration class 6 * (or a nested component class declared within a configuration/component class, 7 * to be auto-registered as well), and mark it accordingly. 8 * @param beanDef the bean definition to check 9 * @param metadataReaderFactory the current factory in use by the caller 10 * @return whether the candidate qualifies as (any kind of) configuration class 11 */ 12 public static boolean checkConfigurationClassCandidate( 13 BeanDefinition beanDef, MetadataReaderFactory metadataReaderFactory) { 14 15 // 获取bean定义信息中的class类名 16 String className = beanDef.getBeanClassName(); 17 // 如果className为空,或者bean定义信息中的factoryMethod不等于空,那么直接返回 18 if (className == null || beanDef.getFactoryMethodName() != null) { 19 return false; 20 } 21 22 AnnotationMetadata metadata; 23 // 通过注解注入的db都是AnnotatedGenericBeanDefinition,实现了AnnotatedBeanDefinition 24 // spring内部的bd是RootBeanDefinition,实现了AbstractBeanDefinition 25 // 此处主要用于判断是否归属于AnnotatedBeanDefinition 26 if (beanDef instanceof AnnotatedBeanDefinition && 27 className.equals(((AnnotatedBeanDefinition) beanDef).getMetadata().getClassName())) { 28 // Can reuse the pre-parsed metadata from the given BeanDefinition... 29 // 从当前bean的定义信息中获取元数据信息 30 metadata = ((AnnotatedBeanDefinition) beanDef).getMetadata(); 31 } 32 // 判断是否是spring中默认的BeanDefinition 33 else if (beanDef instanceof AbstractBeanDefinition && ((AbstractBeanDefinition) beanDef).hasBeanClass()) { 34 // Check already loaded Class if present... 35 // since we possibly can't even load the class file for this Class. 36 // 获取当前bean对象的Class对象 37 Class<?> beanClass = ((AbstractBeanDefinition) beanDef).getBeanClass(); 38 // 如果class实例是下面四种类或接口的子类、父接口等任何一种情况,直接返回 39 if (BeanFactoryPostProcessor.class.isAssignableFrom(beanClass) || 40 BeanPostProcessor.class.isAssignableFrom(beanClass) || 41 AopInfrastructureBean.class.isAssignableFrom(beanClass) || 42 EventListenerFactory.class.isAssignableFrom(beanClass)) { 43 return false; 44 } 45 // 为给定类创建新的AnnotationMetadata实例 46 metadata = AnnotationMetadata.introspect(beanClass); 47 } 48 // 如果上述两种情况都不符合 49 else { 50 try { 51 // 获取className的MetadataReader实例 52 MetadataReader metadataReader = metadataReaderFactory.getMetadataReader(className); 53 // 读取底层类的完整注释元数据,包括带注解方法的元数据 54 metadata = metadataReader.getAnnotationMetadata(); 55 } 56 catch (IOException ex) { 57 if (logger.isDebugEnabled()) { 58 logger.debug("Could not find class file for introspecting configuration annotations: " + 59 className, ex); 60 } 61 return false; 62 } 63 } 64 65 // 获取bean定义的元数据被@Configuration注解标注的属性字典值 66 Map<String, Object> config = metadata.getAnnotationAttributes(Configuration.class.getName()); 67 // 如果bean被@Configuration注解标注,且属性proxyBeanMethods为false(使用代理模式),则将bean定义记为full 68 if (config != null && !Boolean.FALSE.equals(config.get("proxyBeanMethods"))) { 69 beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_FULL); 70 } 71 // 如果bean被@configuration注解标注,且被注解@Component,@ComponentScan、@Import、@ImportResource或者@Bean标记的方法,则将bean定义标记为lite 72 else if (config != null || isConfigurationCandidate(metadata)) { 73 beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_LITE); 74 } 75 else { 76 return false; 77 } 78 79 // It's a full or lite configuration candidate... Let's determine the order value, if any. 80 // bean定义是一个标记为full或lite的候选项,如果设置order则设置order属性值 81 Integer order = getOrder(metadata); 82 // 如果值不为空的话,那么直接设置值到具体的beanDefinition 83 if (order != null) { 84 // 设置bean定义的order值 85 beanDef.setAttribute(ORDER_ATTRIBUTE, order); 86 } 87 88 return true; 89 }
第31行,当前BeanDefinition封装成BeanDefinitionHolder对象加到configCandidates集合中,标明这是一个配置类,后续进行解析。
按照order进行排序操作,判断当前的配置里面是否有自定义的beanName生成器,有的话加载。
提前创建一个配置类的解析器对象,提前准备存放holder对象的集合,提前准备已经处理过的存放集合。
第88行,开始处理整个的解析工作。
1 /** 2 * 构建和验证一个类是否被@Configuration修饰,并做相关的解析工作 3 * 4 * 如果你对此方法了解清楚了,那么springboot的自动装配原理就清楚了 5 * 6 * Build and validate a configuration model based on the registry of 7 * {@link Configuration} classes. 8 */ 9 public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) { 10 // 创建存放BeanDefinitionHolder的对象集合 11 List<BeanDefinitionHolder> configCandidates = new ArrayList<>(); 12 // 当前registry就是DefaultListableBeanFactory,获取所有已经注册的BeanDefinition的beanName 13 String[] candidateNames = registry.getBeanDefinitionNames(); 14 15 // 遍历所有要处理的beanDefinition的名称,筛选对应的beanDefinition(被注解修饰的) 16 for (String beanName : candidateNames) { 17 // 获取指定名称的BeanDefinition对象 18 BeanDefinition beanDef = registry.getBeanDefinition(beanName); 19 // 如果beanDefinition中的configurationClass属性不等于空,那么意味着已经处理过,输出日志信息 20 if (beanDef.getAttribute(ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTE) != null) { 21 if (logger.isDebugEnabled()) { 22 logger.debug("Bean definition has already been processed as a configuration class: " + beanDef); 23 } 24 } 25 // 判断当前BeanDefinition是否是一个配置类,并为BeanDefinition设置属性为lite或者full,此处设置属性值是为了后续进行调用 26 // 如果Configuration配置proxyBeanMethods代理为true则为full 27 // 如果加了@Bean、@Component、@ComponentScan、@Import、@ImportResource注解,则设置为lite 28 // 如果配置类上被@Order注解标注,则设置BeanDefinition的order属性值 29 else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) { 30 // 添加到对应的集合对象中 31 configCandidates.add(new BeanDefinitionHolder(beanDef, beanName)); 32 } 33 } 34 35 // Return immediately if no @Configuration classes were found 36 // 如果没有发现任何配置类,则直接返回 37 if (configCandidates.isEmpty()) { 38 return; 39 } 40 41 // Sort by previously determined @Order value, if applicable 42 // 如果适用,则按照先前确定的@Order的值排序 43 configCandidates.sort((bd1, bd2) -> { 44 int i1 = ConfigurationClassUtils.getOrder(bd1.getBeanDefinition()); 45 int i2 = ConfigurationClassUtils.getOrder(bd2.getBeanDefinition()); 46 return Integer.compare(i1, i2); 47 }); 48 49 // Detect any custom bean name generation strategy supplied through the enclosing application context 50 // 判断当前类型是否是SingletonBeanRegistry类型 51 SingletonBeanRegistry sbr = null; 52 if (registry instanceof SingletonBeanRegistry) { 53 // 类型的强制转换 54 sbr = (SingletonBeanRegistry) registry; 55 // 判断是否有自定义的beanName生成器 56 if (!this.localBeanNameGeneratorSet) { 57 // 获取自定义的beanName生成器 58 BeanNameGenerator generator = (BeanNameGenerator) sbr.getSingleton( 59 AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR); 60 // 如果有自定义的命名生成策略 61 if (generator != null) { 62 //设置组件扫描的beanName生成策略 63 this.componentScanBeanNameGenerator = generator; 64 // 设置import bean name生成策略 65 this.importBeanNameGenerator = generator; 66 } 67 } 68 } 69 70 // 如果环境对象等于空,那么就重新创建新的环境对象 71 if (this.environment == null) { 72 this.environment = new StandardEnvironment(); 73 } 74 75 // Parse each @Configuration class 76 // 实例化ConfigurationClassParser类,并初始化相关的参数,完成配置类的解析工作 77 ConfigurationClassParser parser = new ConfigurationClassParser( 78 this.metadataReaderFactory, this.problemReporter, this.environment, 79 this.resourceLoader, this.componentScanBeanNameGenerator, registry); 80 81 // 创建两个集合对象, 82 // 存放相关的BeanDefinitionHolder对象 83 Set<BeanDefinitionHolder> candidates = new LinkedHashSet<>(configCandidates); 84 // 存放扫描包下的所有bean 85 Set<ConfigurationClass> alreadyParsed = new HashSet<>(configCandidates.size()); 86 do { 87 // 解析带有@Controller、@Import、@ImportResource、@ComponentScan、@ComponentScans、@Bean的BeanDefinition 88 parser.parse(candidates); 89 // 将解析完的Configuration配置类进行校验,1、配置类不能是final,2、@Bean修饰的方法必须可以重写以支持CGLIB 90 parser.validate(); 91 92 // 获取所有的bean,包括扫描的bean对象,@Import导入的bean对象 93 Set<ConfigurationClass> configClasses = new LinkedHashSet<>(parser.getConfigurationClasses()); 94 // 清除掉已经解析处理过的配置类 95 configClasses.removeAll(alreadyParsed); 96 97 // Read the model and create bean definitions based on its content 98 // 判断读取器是否为空,如果为空的话,就创建完全填充好的ConfigurationClass实例的读取器 99 if (this.reader == null) { 100 this.reader = new ConfigurationClassBeanDefinitionReader( 101 registry, this.sourceExtractor, this.resourceLoader, this.environment, 102 this.importBeanNameGenerator, parser.getImportRegistry()); 103 } 104 // 核心方法,将完全填充好的ConfigurationClass实例转化为BeanDefinition注册入IOC容器 105 this.reader.loadBeanDefinitions(configClasses); 106 // 添加到已经处理的集合中 107 alreadyParsed.addAll(configClasses); 108 109 candidates.clear(); 110 // 这里判断registry.getBeanDefinitionCount() > candidateNames.length的目的是为了知道reader.loadBeanDefinitions(configClasses)这一步有没有向BeanDefinitionMap中添加新的BeanDefinition 111 // 实际上就是看配置类(例如AppConfig类会向BeanDefinitionMap中添加bean) 112 // 如果有,registry.getBeanDefinitionCount()就会大于candidateNames.length 113 // 这样就需要再次遍历新加入的BeanDefinition,并判断这些bean是否已经被解析过了,如果未解析,需要重新进行解析 114 // 这里的AppConfig类向容器中添加的bean,实际上在parser.parse()这一步已经全部被解析了 115 if (registry.getBeanDefinitionCount() > candidateNames.length) { 116 String[] newCandidateNames = registry.getBeanDefinitionNames(); 117 Set<String> oldCandidateNames = new HashSet<>(Arrays.asList(candidateNames)); 118 Set<String> alreadyParsedClasses = new HashSet<>(); 119 for (ConfigurationClass configurationClass : alreadyParsed) { 120 alreadyParsedClasses.add(configurationClass.getMetadata().getClassName()); 121 } 122 // 如果有未解析的类,则将其添加到candidates中,这样candidates不为空,就会进入到下一次的while的循环中 123 for (String candidateName : newCandidateNames) { 124 if (!oldCandidateNames.contains(candidateName)) { 125 BeanDefinition bd = registry.getBeanDefinition(candidateName); 126 if (ConfigurationClassUtils.checkConfigurationClassCandidate(bd, this.metadataReaderFactory) && 127 !alreadyParsedClasses.contains(bd.getBeanClassName())) { 128 candidates.add(new BeanDefinitionHolder(bd, candidateName)); 129 } 130 } 131 } 132 candidateNames = newCandidateNames; 133 } 134 } 135 while (!candidates.isEmpty()); 136 137 // Register the ImportRegistry as a bean in order to support ImportAware @Configuration classes 138 if (sbr != null && !sbr.containsSingleton(IMPORT_REGISTRY_BEAN_NAME)) { 139 sbr.registerSingleton(IMPORT_REGISTRY_BEAN_NAME, parser.getImportRegistry()); 140 } 141 142 if (this.metadataReaderFactory instanceof CachingMetadataReaderFactory) { 143 // Clear cache in externally provided MetadataReaderFactory; this is a no-op 144 // for a shared cache since it'll be cleared by the ApplicationContext. 145 ((CachingMetadataReaderFactory) this.metadataReaderFactory).clearCache(); 146 } 147 }
入参是一个集合,解析要循环进行判定,获取当前BeanDefinition,判断BeanDefinition归属于哪个类型。
1 public void parse(Set<BeanDefinitionHolder> configCandidates) { 2 // 循环遍历configCandidates 3 for (BeanDefinitionHolder holder : configCandidates) { 4 // 获取BeanDefinition 5 BeanDefinition bd = holder.getBeanDefinition(); 6 // 根据BeanDefinition类型的不同,调用parse不同的重载方法,实际上最终都是调用processConfigurationClass()方法 7 try { 8 // 注解类型 9 if (bd instanceof AnnotatedBeanDefinition) { 10 parse(((AnnotatedBeanDefinition) bd).getMetadata(), holder.getBeanName()); 11 } 12 // 有class对象的 13 else if (bd instanceof AbstractBeanDefinition && ((AbstractBeanDefinition) bd).hasBeanClass()) { 14 parse(((AbstractBeanDefinition) bd).getBeanClass(), holder.getBeanName()); 15 } 16 else { 17 parse(bd.getBeanClassName(), holder.getBeanName()); 18 } 19 } 20 catch (BeanDefinitionStoreException ex) { 21 throw ex; 22 } 23 catch (Throwable ex) { 24 throw new BeanDefinitionStoreException( 25 "Failed to parse configuration class [" + bd.getBeanClassName() + "]", ex); 26 } 27 } 28 29 // 执行找到的DeferredImportSelector 30 // DeferredImportSelector是ImportSelector的一个子类 31 // ImportSelector被设计成和@Import注解同样的效果,但是实现了ImportSelector的类可以条件性的决定导入某些配置 32 // DeferredImportSelector的设计魔都是在所有其他的配置类被处理后才进行处理 33 this.deferredImportSelectorHandler.process(); 34 }
首先判断是否含有@Conditional注解,做相应的条件判断再做解析。第9行,相当于一个本地缓存,比如最开始有一个配置类MyComponentScan类,后面可以再通过@Import(MyComponentScan.class)注入进来。没有必要对MyComponentScan进行两遍处理,所以后面要把处理的configClass保存起来。若要解析当前类,需要不断循环解析父类。进入第36行,doXxx方法开始对当前类包含的注解都进行解析和处理。
1 protected void processConfigurationClass(ConfigurationClass configClass, Predicate<String> filter) throws IOException { 2 // 判断是否跳过解析 3 if (this.conditionEvaluator.shouldSkip(configClass.getMetadata(), ConfigurationPhase.PARSE_CONFIGURATION)) { 4 return; 5 } 6 7 // 第一次进入的时候,configurationClass的size为0,existingClass肯定为null,在此处处理configuration重复import 8 // 如果同一个配置类被处理两次,两次都属于被import的则合并导入类,返回,如果配置类不是被导入的,则移除旧的使用新的配置类 9 ConfigurationClass existingClass = this.configurationClasses.get(configClass); 10 if (existingClass != null) { 11 if (configClass.isImported()) { 12 if (existingClass.isImported()) { 13 // 如果要处理的配置类configclass在已经分析处理的配置类记录中已存在,合并两者的importBy属性 14 existingClass.mergeImportedBy(configClass); 15 } 16 // Otherwise ignore new imported config class; existing non-imported class overrides it. 17 return; 18 } 19 else { 20 // Explicit bean definition found, probably replacing an import. 21 // Let's remove the old one and go with the new one. 22 this.configurationClasses.remove(configClass); 23 this.knownSuperclasses.values().removeIf(configClass::equals); 24 } 25 } 26 27 // Recursively process the configuration class and its superclass hierarchy. 28 29 // 处理配置类,由于配置类可能存在父类(若父类的全类名是以java开头的,则除外),所有需要将configClass变成sourceClass去解析,然后返回sourceClass的父类。 30 // 如果此时父类为空,则不会进行while循环去解析,如果父类不为空,则会循环的去解析父类 31 // SourceClass的意义:简单的包装类,目的是为了以统一的方式去处理带有注解的类,不管这些类是如何加载的 32 // 如果无法理解,可以把它当做一个黑盒,不会影响看spring源码的主流程 33 SourceClass sourceClass = asSourceClass(configClass, filter); 34 do { 35 // 解析各种注解 36 sourceClass = doProcessConfigurationClass(configClass, sourceClass, filter); 37 } 38 while (sourceClass != null); 39 40 // 将解析的配置类存储起来,这样回到parse方法时,能取到值 41 this.configurationClasses.put(configClass, configClass); 42 }
当前的类如果被@Component注解所修饰(注意@Configuration继承了@Component,@Configuration包括@Component),递归处理内部类,注意是外部类@Component注解递归调内部类解析,从最内部的类解析剩下的注解,往外层解析,直到最外部类解析完全部注解。
对当前的@PropertySource做一个解析工作,加载外部配置文件进来,加入到beanFactory中。
第37行判断是否包含@ComponentScan注解,如果包含创建componentScanParser结果集对象,第47行调用扫描包的解析器方法去解析。
第67行解析@Import注解,导入一些额外的配置类,同时完成具体类的实例化工作,接着处理@ImportResource
处理@Bean,注意是通过asm直接读取字节码技术获取的方法,由于具有标准的顺序,而用反射顺序会乱。最后把处理完的beanMethod对象加到configClass中,configClass是由LinkedHashSet实现的。
1 /** 2 * Apply processing and build a complete {@link ConfigurationClass} by reading the 3 * annotations, members and methods from the source class. This method can be called 4 * multiple times as relevant sources are discovered. 5 * @param configClass the configuration class being build 6 * @param sourceClass a source class 7 * @return the superclass, or {@code null} if none found or previously processed 8 */ 9 @Nullable 10 protected final SourceClass doProcessConfigurationClass( 11 ConfigurationClass configClass, SourceClass sourceClass, Predicate<String> filter) 12 throws IOException { 13 // @Configuration继承了@Component 14 if (configClass.getMetadata().isAnnotated(Component.class.getName())) { 15 // Recursively process any member (nested) classes first 16 // 递归处理内部类,因为内部类也是一个配置类,配置类上有@configuration注解,该注解继承@Component,if判断为true,调用processMemberClasses方法,递归解析配置类中的内部类 17 processMemberClasses(configClass, sourceClass, filter); 18 } 19 20 // Process any @PropertySource annotations 21 // 如果配置类上加了@PropertySource注解,那么就解析加载properties文件,并将属性添加到spring上下文中 22 for (AnnotationAttributes propertySource : AnnotationConfigUtils.attributesForRepeatable( 23 sourceClass.getMetadata(), PropertySources.class, 24 org.springframework.context.annotation.PropertySource.class)) { 25 if (this.environment instanceof ConfigurableEnvironment) { 26 processPropertySource(propertySource); 27 } 28 else { 29 logger.info("Ignoring @PropertySource annotation on [" + sourceClass.getMetadata().getClassName() + 30 "]. Reason: Environment must implement ConfigurableEnvironment"); 31 } 32 } 33 34 // Process any @ComponentScan annotations 35 // 处理@ComponentScan或者@ComponentScans注解,并将扫描包下的所有bean转换成填充后的ConfigurationClass 36 // 此处就是将自定义的bean加载到IOC容器,因为扫描到的类可能也添加了@ComponentScan和@ComponentScans注解,因此需要进行递归解析 37 Set<AnnotationAttributes> componentScans = AnnotationConfigUtils.attributesForRepeatable( 38 sourceClass.getMetadata(), ComponentScans.class, ComponentScan.class); 39 if (!componentScans.isEmpty() && 40 !this.conditionEvaluator.shouldSkip(sourceClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN)) { 41 for (AnnotationAttributes componentScan : componentScans) { 42 // The config class is annotated with @ComponentScan -> perform the scan immediately 43 // 解析@ComponentScan和@ComponentScans配置的扫描的包所包含的类 44 // 比如 basePackages = com.mashibing, 那么在这一步会扫描出这个包及子包下的class,然后将其解析成BeanDefinition 45 // (BeanDefinition可以理解为等价于BeanDefinitionHolder) 46 Set<BeanDefinitionHolder> scannedBeanDefinitions = 47 this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName()); 48 // Check the set of scanned definitions for any further config classes and parse recursively if needed 49 // 通过上一步扫描包com.mashibing,有可能扫描出来的bean中可能也添加了ComponentScan或者ComponentScans注解. 50 //所以这里需要循环遍历一次,进行递归(parse),继续解析,直到解析出的类上没有ComponentScan和ComponentScans 51 for (BeanDefinitionHolder holder : scannedBeanDefinitions) { 52 BeanDefinition bdCand = holder.getBeanDefinition().getOriginatingBeanDefinition(); 53 if (bdCand == null) { 54 bdCand = holder.getBeanDefinition(); 55 } 56 // 判断是否是一个配置类,并设置full或lite属性 57 if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) { 58 // 通过递归方法进行解析 59 parse(bdCand.getBeanClassName(), holder.getBeanName()); 60 } 61 } 62 } 63 } 64 65 // Process any @Import annotations 66 // 处理@Import注解 67 processImports(configClass, sourceClass, getImports(sourceClass), filter, true); 68 69 // Process any @ImportResource annotations 70 // 处理@ImportResource注解,导入spring的配置文件 71 AnnotationAttributes importResource = 72 AnnotationConfigUtils.attributesFor(sourceClass.getMetadata(), ImportResource.class); 73 if (importResource != null) { 74 String[] resources = importResource.getStringArray("locations"); 75 Class<? extends BeanDefinitionReader> readerClass = importResource.getClass("reader"); 76 for (String resource : resources) { 77 String resolvedResource = this.environment.resolveRequiredPlaceholders(resource); 78 configClass.addImportedResource(resolvedResource, readerClass); 79 } 80 } 81 82 // Process individual @Bean methods 83 // 处理加了@Bean注解的方法,将@Bean方法转化为BeanMethod对象,保存再集合中 84 Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass); 85 for (MethodMetadata methodMetadata : beanMethods) { 86 configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass)); 87 } 88 89 // Process default methods on interfaces 90 // 处理接口的默认方法实现,从jdk8开始,接口中的方法可以有自己的默认实现,因此如果这个接口的方法加了@Bean注解,也需要被解析 91 processInterfaces(configClass, sourceClass); 92 93 // Process superclass, if any 94 // 解析父类,如果被解析的配置类继承了某个类,那么配置类的父类也会被进行解析 95 if (sourceClass.getMetadata().hasSuperClass()) { 96 String superclass = sourceClass.getMetadata().getSuperClassName(); 97 if (superclass != null && !superclass.startsWith("java") && 98 !this.knownSuperclasses.containsKey(superclass)) { 99 this.knownSuperclasses.put(superclass, configClass); 100 // Superclass found, return its annotation metadata and recurse 101 return sourceClass.getSuperClass(); 102 } 103 } 104 105 // No superclass -> processing is complete 106 return null; 107 }
解析并设置注解中包括的所有属性值,第67行开始对包下所有类进行解析工作,最后把扫描到的类调用registerBeanDefinition方法注册到beanFactory去。遍历扫描到的beanDefinition,递归解析处理。
1 public Set<BeanDefinitionHolder> parse(AnnotationAttributes componentScan, final String declaringClass) { 2 // 创建对应的扫描类 3 ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(this.registry, 4 componentScan.getBoolean("useDefaultFilters"), this.environment, this.resourceLoader); 5 6 // 获取@ComponentScan的参数,并进行参数的设置工作 7 Class<? extends BeanNameGenerator> generatorClass = componentScan.getClass("nameGenerator"); 8 boolean useInheritedGenerator = (BeanNameGenerator.class == generatorClass); 9 scanner.setBeanNameGenerator(useInheritedGenerator ? this.beanNameGenerator : 10 BeanUtils.instantiateClass(generatorClass)); 11 12 // 获取scopedProxy属性 13 ScopedProxyMode scopedProxyMode = componentScan.getEnum("scopedProxy"); 14 if (scopedProxyMode != ScopedProxyMode.DEFAULT) { 15 scanner.setScopedProxyMode(scopedProxyMode); 16 } 17 else { 18 Class<? extends ScopeMetadataResolver> resolverClass = componentScan.getClass("scopeResolver"); 19 scanner.setScopeMetadataResolver(BeanUtils.instantiateClass(resolverClass)); 20 } 21 22 // 获取resourcePattern属性 23 scanner.setResourcePattern(componentScan.getString("resourcePattern")); 24 25 // 获取includeFilters属性 26 for (AnnotationAttributes filter : componentScan.getAnnotationArray("includeFilters")) { 27 for (TypeFilter typeFilter : typeFiltersFor(filter)) { 28 scanner.addIncludeFilter(typeFilter); 29 } 30 } 31 // 获取excludeFilters属性 32 for (AnnotationAttributes filter : componentScan.getAnnotationArray("excludeFilters")) { 33 for (TypeFilter typeFilter : typeFiltersFor(filter)) { 34 scanner.addExcludeFilter(typeFilter); 35 } 36 } 37 38 // 获取lazyInit属性 39 boolean lazyInit = componentScan.getBoolean("lazyInit"); 40 if (lazyInit) { 41 scanner.getBeanDefinitionDefaults().setLazyInit(true); 42 } 43 44 Set<String> basePackages = new LinkedHashSet<>(); 45 // 获取basePackages属性 46 String[] basePackagesArray = componentScan.getStringArray("basePackages"); 47 for (String pkg : basePackagesArray) { 48 String[] tokenized = StringUtils.tokenizeToStringArray(this.environment.resolvePlaceholders(pkg), 49 ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS); 50 Collections.addAll(basePackages, tokenized); 51 } 52 // 获取basePackageClasses属性 53 for (Class<?> clazz : componentScan.getClassArray("basePackageClasses")) { 54 basePackages.add(ClassUtils.getPackageName(clazz)); 55 } 56 if (basePackages.isEmpty()) { 57 basePackages.add(ClassUtils.getPackageName(declaringClass)); 58 } 59 60 scanner.addExcludeFilter(new AbstractTypeHierarchyTraversingFilter(false, false) { 61 @Override 62 protected boolean matchClassName(String className) { 63 return declaringClass.equals(className); 64 } 65 }); 66 // 开始执行扫描,最终的扫描器是ClassPathBeanDefinitionScanner 67 return scanner.doScan(StringUtils.toStringArray(basePackages)); 68 }
开始进行包扫描方法,遍历包路径,根据包名扫描basePackage,将符合要求的beanDefinition全部找出来进行属性设置,注册beanFactory返回。
1 /** 2 * Perform a scan within the specified base packages, 3 * returning the registered bean definitions. 4 * <p>This method does <i>not</i> register an annotation config processor 5 * but rather leaves this up to the caller. 6 * @param basePackages the packages to check for annotated classes 7 * @return set of beans registered if any for tooling registration purposes (never {@code null}) 8 */ 9 protected Set<BeanDefinitionHolder> doScan(String... basePackages) { 10 Assert.notEmpty(basePackages, "At least one base package must be specified"); 11 Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<>(); 12 // 遍历basePackages 13 for (String basePackage : basePackages) { 14 // 扫描basePackage,将符合要求的bean定义全部找出来 15 Set<BeanDefinition> candidates = findCandidateComponents(basePackage); 16 // 遍历所有候选的bean定义 17 for (BeanDefinition candidate : candidates) { 18 // 解析@Scope注解,包括scopeName和proxyMode 19 ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate); 20 candidate.setScope(scopeMetadata.getScopeName()); 21 // 使用beanName生成器来生成beanName 22 String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry); 23 if (candidate instanceof AbstractBeanDefinition) { 24 // 处理beanDefinition对象,例如,此bean是否可以自动装配到其他bean中 25 postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName); 26 } 27 if (candidate instanceof AnnotatedBeanDefinition) { 28 // 处理定义在目标类上的通用注解,包括@Lazy,@Primary,@DependsOn,@Role,@Description 29 AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate); 30 } 31 // 检查beanName是否已经注册过,如果注册过,检查是否兼容 32 if (checkCandidate(beanName, candidate)) { 33 // 将当前遍历be 34 an的bean定义和beanName封装成BeanDefinitionHolder 35 BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName); 36 // 根据proxyMode的值,选择是否创建作用域代理 37 definitionHolder = 38 AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry); 39 beanDefinitions.add(definitionHolder); 40 // 注册beanDefinition 41 registerBeanDefinition(definitionHolder, this.registry); 42 } 43 } 44 } 45 return beanDefinitions; 46 }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!