这里分析bean定义是如何加载到容器里面的
加载步骤图 加载步骤如图显示:
加载源码分析 I0 refresh org.springframework.context.support.AbstractApplicationContext#refresh 加载入口
1 2 3 4 5 public AnnotationConfigApplicationContext (Class... annotatedClasses) { this (); this .register(annotatedClasses); this .refresh(); }
I1 invokeBeanFactoryPostProcessors org.springframework.context.support.AbstractApplicationContext#invokeBeanFactoryPostProcessors
执行BeanFactory后置处理(实例化bean工厂的后置处理器)
1 2 3 4 5 6 7 8 protected void invokeBeanFactoryPostProcessors (ConfigurableListableBeanFactory beanFactory) { PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, this .getBeanFactoryPostProcessors()); if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean("loadTimeWeaver" )) { beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory)); beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader())); } }
I1.1 processConfigBeanDefinitions 在org.springframework.context.support.PostProcessorRegistrationDelegate#invokeBeanDefinitionRegistryPostProcessors 方法内部,
org.springframework.context.annotation.ConfigurationClassPostProcessor#processConfigBeanDefinitions
扫描、解析、注册所有配置类的Bean定义
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 public void processConfigBeanDefinitions (BeanDefinitionRegistry registry) { List<BeanDefinitionHolder> configCandidates = new ArrayList(); String[] candidateNames = registry.getBeanDefinitionNames(); String[] var4 = candidateNames; int var5 = candidateNames.length; for (int var6 = 0 ; var6 < var5; ++var6) { String beanName = var4[var6]; BeanDefinition beanDef = registry.getBeanDefinition(beanName); if (!ConfigurationClassUtils.isFullConfigurationClass(beanDef) && !ConfigurationClassUtils.isLiteConfigurationClass(beanDef)) { if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this .metadataReaderFactory)) { configCandidates.add(new BeanDefinitionHolder(beanDef, beanName)); } } else if (this .logger.isDebugEnabled()) { this .logger.debug("Bean definition has already been processed as a configuration class: " + beanDef); } } if (!configCandidates.isEmpty()) { configCandidates.sort((bd1, bd2) -> { int i1 = ConfigurationClassUtils.getOrder(bd1.getBeanDefinition()); int i2 = ConfigurationClassUtils.getOrder(bd2.getBeanDefinition()); return Integer.compare(i1, i2); }); SingletonBeanRegistry sbr = null ; if (registry instanceof SingletonBeanRegistry) { sbr = (SingletonBeanRegistry)registry; if (!this .localBeanNameGeneratorSet) { BeanNameGenerator generator = (BeanNameGenerator)sbr.getSingleton("org.springframework.context.annotation.internalConfigurationBeanNameGenerator" ); if (generator != null ) { this .componentScanBeanNameGenerator = generator; this .importBeanNameGenerator = generator; } } } if (this .environment == null ) { this .environment = new StandardEnvironment(); } ConfigurationClassParser parser = new ConfigurationClassParser(this .metadataReaderFactory, this .problemReporter, this .environment, this .resourceLoader, this .componentScanBeanNameGenerator, registry); Set<BeanDefinitionHolder> candidates = new LinkedHashSet(configCandidates); HashSet alreadyParsed = new HashSet(configCandidates.size()); do { parser.parse(candidates); parser.validate(); Set<ConfigurationClass> configClasses = new LinkedHashSet(parser.getConfigurationClasses()); configClasses.removeAll(alreadyParsed); if (this .reader == null ) { this .reader = new ConfigurationClassBeanDefinitionReader(registry, this .sourceExtractor, this .resourceLoader, this .environment, this .importBeanNameGenerator, parser.getImportRegistry()); } this .reader.loadBeanDefinitions(configClasses); alreadyParsed.addAll(configClasses); candidates.clear(); if (registry.getBeanDefinitionCount() > candidateNames.length) { String[] newCandidateNames = registry.getBeanDefinitionNames(); Set<String> oldCandidateNames = new HashSet(Arrays.asList(candidateNames)); Set<String> alreadyParsedClasses = new HashSet(); Iterator var12 = alreadyParsed.iterator(); while (var12.hasNext()) { ConfigurationClass configurationClass = (ConfigurationClass)var12.next(); alreadyParsedClasses.add(configurationClass.getMetadata().getClassName()); } String[] var23 = newCandidateNames; int var24 = newCandidateNames.length; for (int var14 = 0 ; var14 < var24; ++var14) { String candidateName = var23[var14]; if (!oldCandidateNames.contains(candidateName)) { BeanDefinition bd = registry.getBeanDefinition(candidateName); if (ConfigurationClassUtils.checkConfigurationClassCandidate(bd, this .metadataReaderFactory) && !alreadyParsedClasses.contains(bd.getBeanClassName())) { candidates.add(new BeanDefinitionHolder(bd, candidateName)); } } } ... } } }
i1.1.1 parse org.springframework.context.annotation.ConfigurationClassParser#parse
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 public void parse (Set<BeanDefinitionHolder> configCandidates) { this .deferredImportSelectors = new LinkedList<DeferredImportSelectorHolder>(); for (BeanDefinitionHolder holder : configCandidates) { BeanDefinition bd = holder.getBeanDefinition(); try { if (bd instanceof AnnotatedBeanDefinition) { parse(((AnnotatedBeanDefinition) bd).getMetadata(), holder.getBeanName()); } else if (bd instanceof AbstractBeanDefinition && ((AbstractBeanDefinition) bd).hasBeanClass()) { parse(((AbstractBeanDefinition) bd).getBeanClass(), holder.getBeanName()); } else { parse(bd.getBeanClassName(), holder.getBeanName()); } } catch (BeanDefinitionStoreException ex) { throw ex; } catch (Throwable ex) { throw new BeanDefinitionStoreException( "Failed to parse configuration class [" + bd.getBeanClassName() + "]" , ex); } } processDeferredImportSelectors(); }
做了三件事:
1 2 3 1. 实例化deferredImportSelectors2. 遍历配置类,得到BeanDefinition,根据bd类型不同,调用不同的parse方法解析3. 处理deferredImportSelectors
这里的parse方法再往下调用会调到ConfigurationClassParser类的processConfigurationClass方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 public void parse (Set<BeanDefinitionHolder> configCandidates) { ... while (var2.hasNext()) { ... try { if (bd instanceof AnnotatedBeanDefinition) { ## 转到ConfigurationClassParser类的processConfigurationClass this .parse(...); } else if (bd instanceof AbstractBeanDefinition && ((AbstractBeanDefinition)bd).hasBeanClass()) { this .parse(...); } else { this .parse(...); } .......
I1.1.1.1 processConfigurationClass org.springframework.context.annotation.ConfigurationClassParser#processConfigurationClass
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 protected void processConfigurationClass (ConfigurationClass configClass) throws IOException { if (this .conditionEvaluator.shouldSkip(configClass.getMetadata(), ConfigurationPhase.PARSE_CONFIGURATION)) { return ; } ConfigurationClass existingClass = this .configurationClasses.get(configClass); if (existingClass != null ) { if (configClass.isImported()) { if (existingClass.isImported()) { existingClass.mergeImportedBy(configClass); } return ; } else { this .configurationClasses.remove(configClass); for (Iterator<ConfigurationClass> it = this .knownSuperclasses.values().iterator(); it.hasNext(); ) { if (configClass.equals(it.next())) { it.remove(); } } } } SourceClass sourceClass = asSourceClass(configClass); do { sourceClass = doProcessConfigurationClass(configClass, sourceClass); } while (sourceClass != null ); this .configurationClasses.put(configClass, configClass); }
做了四件事:
1 2 3 4 5 6 7 8 1. shouldSkip 方法判断是否跳过:没有被@Conditional 注解所修饰,返回false 如果参数中沒有设置条件注解的生效阶段,是配置类的话直接使用PARSE_CONFIGURATION阶段,递归调用shouldSkip, 否则使用REGISTER_BEAN阶段,递归调用shouldSkip 。获取配置类的条件注解得到条件数据,并添加到集合中 遍历conditions,进行判断,如果阶段不满足条件的话,返回true 并跳过这个bean的解析 2. 判断ConfigurationClassParser的configurationClasses中是否已有该配置类,判断是否需要处理imported3. 递归解析4. 添加到ConfigurationClassParser的configurationClasses中
doProcessConfigurationClass org.springframework.context.annotation.ConfigurationClassParser#doProcessConfigurationClass
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 protected final SourceClass doProcessConfigurationClass (ConfigurationClass configClass, SourceClass sourceClass) throws IOException { processMemberClasses(configClass, sourceClass); for (AnnotationAttributes propertySource : AnnotationConfigUtils.attributesForRepeatable( sourceClass.getMetadata(), PropertySources.class, org.springframework.context.annotation.PropertySource.class)) { if (this .environment instanceof ConfigurableEnvironment) { processPropertySource(propertySource); } else { logger.warn("Ignoring @PropertySource annotation on [" + sourceClass.getMetadata().getClassName() + "]. Reason: Environment must implement ConfigurableEnvironment" ); } } Set<AnnotationAttributes> componentScans = AnnotationConfigUtils.attributesForRepeatable( sourceClass.getMetadata(), ComponentScans.class, ComponentScan.class); if (!componentScans.isEmpty() && !this .conditionEvaluator.shouldSkip(sourceClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN)) { for (AnnotationAttributes componentScan : componentScans) { Set<BeanDefinitionHolder> scannedBeanDefinitions = this .componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName()); for (BeanDefinitionHolder holder : scannedBeanDefinitions) { if (ConfigurationClassUtils.checkConfigurationClassCandidate(holder.getBeanDefinition(), this .metadataReaderFactory)) { parse(holder.getBeanDefinition().getBeanClassName(), holder.getBeanName()); } } } } processImports(configClass, sourceClass, getImports(sourceClass), true ); if (sourceClass.getMetadata().isAnnotated(ImportResource.class.getName())) { AnnotationAttributes importResource = AnnotationConfigUtils.attributesFor(sourceClass.getMetadata(), ImportResource.class); String[] resources = importResource.getStringArray("locations" ); Class<? extends BeanDefinitionReader> readerClass = importResource.getClass("reader" ); for (String resource : resources) { String resolvedResource = this .environment.resolveRequiredPlaceholders(resource); configClass.addImportedResource(resolvedResource, readerClass); } } Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass); for (MethodMetadata methodMetadata : beanMethods) { configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass)); } processInterfaces(configClass, sourceClass); if (sourceClass.getMetadata().hasSuperClass()) { String superclass = sourceClass.getMetadata().getSuperClassName(); if (!superclass.startsWith("java" ) && !this .knownSuperclasses.containsKey(superclass)) { this .knownSuperclasses.put(superclass, configClass); return sourceClass.getSuperClass(); } } return null ; }
做了八件事:
1 2 3 4 5 6 7 8 1. 处理内部类2. 处理@PropertySource 注解3. 处理@ComponentScan 注解4. 处理@Import 注解5. 处理@ImportResource 注解6. 处理@Bean 修饰的方法7. 处理接口定义的方法8. 处理父类