1.前言
Spring注解开发中,我们只需求要类上加上@Configuration注解,然后在类中的方法上面加上@Bean注解即可完成Spring Bean组件的注册。相较于之前的xml配置文件定义注册组件简化了非常多。那么Spring底层是如何处理@Configuration注解来完成Spring组件的注册,下面通过源码一步一步进行分析。
2.准备工作
Spring版本:2.2.13.RELEASE
源码中涉及的类:
- ConfigurationClassPostProcessor
- ConfigurationClassParser
- ConfigurationClass
- BeanMethod
- ConfigurationClassBeanDefinitionReader
- ConfigurationClassEnhancer
- ConfigurationClassUtils
说明:文中统一将被@Configuration注解标注的类称为配置类
3.涉及相关类说明
ConfigurationClassPostProcessor
配置类的后知处理器,其中实现了BeanDefinitionRegistryPostProcessor接口,可以拿到BeanDefinitionRegistry对象手动注册组件,也是整个解析流程的入口
ConfigurationClassParser
配置类解析器,解析配置类,封装成一个个的ConfigurationClass对象
ConfigurationClass
配置类经解析后的实体对象
BeanMethod
被@Bean注解标注的方法解析后的实体对象
ConfigurationClassBeanDefinitionReader
用于读取注册配置类中定义的组件
ConfigurationClassEnhancer
对配置类进行代理增强的角色类
ConfigurationClassUtils
配置类解析相关的工具类
4.源码流程分析
ConfigurationClassPostProcessor作为入口类,类的层次结构入上图,我们只需要关心BeanDefinitionRegistryPostProcessor和BeanFactoryPostProcessor两个接口的回调方法BeanFactoryPostProcessor和postProcessBeanFactory。
两个方法的具体实现如下,可以看到两个方法的内部都调用了processConfigBeanDefinitions方法,下面针对此方法进行分析
1 public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) { 2 int registryId = System.identityHashCode(registry); 3 if (this.registriesPostProcessed.contains(registryId)) { 4 throw new IllegalStateException( 5 "postProcessBeanDefinitionRegistry already called on this post-processor against " + registry); 6 } 7 if (this.factoriesPostProcessed.contains(registryId)) { 8 throw new IllegalStateException( 9 "postProcessBeanFactory already called on this post-processor against " + registry); 10 } 11 this.registriesPostProcessed.add(registryId); 12 13 processConfigBeanDefinitions(registry); 14 } 15 16 public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) { 17 int factoryId = System.identityHashCode(beanFactory); 18 if (this.factoriesPostProcessed.contains(factoryId)) { 19 throw new IllegalStateException( 20 "postProcessBeanFactory already called on this post-processor against " + beanFactory); 21 } 22 this.factoriesPostProcessed.add(factoryId); 23 if (!this.registriesPostProcessed.contains(factoryId)) { 24 // BeanDefinitionRegistryPostProcessor hook apparently not supported... 25 // Simply call processConfigurationClasses lazily at this point then. 26 processConfigBeanDefinitions((BeanDefinitionRegistry) beanFactory); 27 } 28 29 enhanceConfigurationClasses(beanFactory); 30 beanFactory.addBeanPostProcessor(new ImportAwareBeanPostProcessor(beanFactory)); 31 }
1.processConfigBeanDefinitions方法分析如下(删除了部分不相关代码)
public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) { // 待处理配置类集合 ListconfigCandidates = new ArrayList<>(); // 获取所有组件名称 String[] candidateNames = registry.getBeanDefinitionNames(); for (String beanName : candidateNames) { // 获取组件定义信息 BeanDefinition beanDef = registry.getBeanDefinition(beanName); // 判断组件是否已经被作为一个配置类处理过 if (beanDef.getAttribute(ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTE) != null) { if (logger.isDebugEnabled()) { logger.debug("Bean definition has already been processed as a configuration class: " + beanDef); } } // 判断组件是否为候选的配置类,如果是则加入待处理集合。checkConfigurationClassCandidate下面具体分析 else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) { configCandidates.add(new BeanDefinitionHolder(beanDef, beanName)); } } // 如果待处理配置类为空,直接返回 if (configCandidates.isEmpty()) { return; } // 对所有配置类进行排序 configCandidates.sort((bd1, bd2) -> { int i1 = ConfigurationClassUtils.getOrder(bd1.getBeanDefinition()); int i2 = ConfigurationClassUtils.getOrder(bd2.getBeanDefinition()); return Integer.compare(i1, i2); }); // 初始化配置类解析器 ConfigurationClassParser parser = new ConfigurationClassParser( this.metadataReaderFactory, this.problemReporter, this.environment, this.resourceLoader, this.componentScanBeanNameGenerator, registry); Set candidates = new LinkedHashSet<>(configCandidates);do { // 解析每一个配置类 parser.parse(candidates); // 验证每一个配置类 parser.validate(); // 获取解析后的所有配置类实体ConfigurationClass Set configClasses = new LinkedHashSet<>(parser.getConfigurationClasses()); // 初始化配置类中定义的组件读取者 if (this.reader == null) { this.reader = new ConfigurationClassBeanDefinitionReader( registry, this.sourceExtractor, this.resourceLoader, this.environment, this.importBeanNameGenerator, parser.getImportRegistry()); }
// 读取配置类中所有被@Bean注解标注的方法,并将每个方法封装成BeanDefinition注册到容器中 this.reader.loadBeanDefinitions(configClasses); } while (!candidates.isEmpty()); }
2.ConfigurationClassUtils.checkConfigurationClassCandidate方法分析
public static boolean checkConfigurationClassCandidate( BeanDefinition beanDef, MetadataReaderFactory metadataReaderFactory) { // 获取组件的全限定类名 String className = beanDef.getBeanClassName(); if (className == null || beanDef.getFactoryMethodName() != null) { return false; } // 下面这一大段代码都是在获取组件类的元数据信息AnnotationMetadata,这里不详细介绍 AnnotationMetadata metadata; if (beanDef instanceof AnnotatedBeanDefinition && className.equals(((AnnotatedBeanDefinition) beanDef).getMetadata().getClassName())) { // Can reuse the pre-parsed metadata from the given BeanDefinition... metadata = ((AnnotatedBeanDefinition) beanDef).getMetadata(); } else if (beanDef instanceof AbstractBeanDefinition && ((AbstractBeanDefinition) beanDef).hasBeanClass()) { // Check already loaded Class if present... // since we possibly can't even load the class file for this Class. Class> beanClass = ((AbstractBeanDefinition) beanDef).getBeanClass(); if (BeanFactoryPostProcessor.class.isAssignableFrom(beanClass) || BeanPostProcessor.class.isAssignableFrom(beanClass) || AopInfrastructureBean.class.isAssignableFrom(beanClass) || EventListenerFactory.class.isAssignableFrom(beanClass)) { return false; } metadata = AnnotationMetadata.introspect(beanClass); } else { try { MetadataReader metadataReader = metadataReaderFactory.getMetadataReader(className); metadata = metadataReader.getAnnotationMetadata(); } catch (IOException ex) { if (logger.isDebugEnabled()) { logger.debug("Could not find class file for introspecting configuration annotations: " + className, ex); } return false; } } // 获取组件类的@Configuration注解属性,如果组件类上不存在@Configuration注解,则返回空 Mapconfig = metadata.getAnnotationAttributes(Configuration.class.getName()); // 如果存在,并且proxyBeanMethods属性的值为true,则标注当前配置类为full,即需要代理增强,为一个代理类 if (config != null && !Boolean.FALSE.equals(config.get("proxyBeanMethods"))) { beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_FULL); } // 如果存在,并且isConfigurationCandidate返回true,则标注当前配置类为lite,即不需要代理增强,为一个普通类 else if (config != null || isConfigurationCandidate(metadata)) { beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_LITE); } // 组件类不存在@Configuration注解,直接返回false else { return false; } // 获取配置类的排序顺序,设置到组件定义属性中 Integer order = getOrder(metadata); if (order != null) { beanDef.setAttribute(ORDER_ATTRIBUTE, order); } return true; }
public static boolean isConfigurationCandidate(AnnotationMetadata metadata) { // 如果配置类为一个接口,则不处理 if (metadata.isInterface()) { return false; } /* * 判断配置类是否存在(@Component,ComponentScan,@Import,ImportResource)注解 * 如果存在上述任意一个注解,则返回true */ for (String indicator : candidateIndicators) { if (metadata.isAnnotated(indicator)) { return true; } } // 如果上述四个注解都不存在,则判断配置类中是否存在被@Bean标注的方法 return hasBeanMethods(metadata); }
3.ConfigurationClassParser.parse方法分析
public void parse(SetconfigCandidates) { for (BeanDefinitionHolder holder : configCandidates) { // 循环每一个配置类的定义信息,然后调用parse方法,下面三个parse重载方法逻辑一样 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); } } this.deferredImportSelectorHandler.process(); } protected final void parse(@Nullable String className, String beanName) throws IOException { Assert.notNull(className, "No bean class name for configuration class bean definition"); MetadataReader reader = this.metadataReaderFactory.getMetadataReader(className); // 将配置类封装成ConfigurationClass后调用processConfigurationClass processConfigurationClass(new ConfigurationClass(reader, beanName), DEFAULT_EXCLUSION_FILTER); } protected final void parse(Class> clazz, String beanName) throws IOException { // 将配置类封装成ConfigurationClass后调用processConfigurationClass processConfigurationClass(new ConfigurationClass(clazz, beanName), DEFAULT_EXCLUSION_FILTER); } protected final void parse(AnnotationMetadata metadata, String beanName) throws IOException { // 将配置类封装成ConfigurationClass后调用processConfigurationClass processConfigurationClass(new ConfigurationClass(metadata, beanName), DEFAULT_EXCLUSION_FILTER); }
4.processConfigurationClass方法分析
protected void processConfigurationClass(ConfigurationClass configClass, Predicatefilter) throws IOException { // 判断配置类是否有@Condition注解,如果有的话根据条件判断是否成立 if (this.conditionEvaluator.shouldSkip(configClass.getMetadata(), ConfigurationPhase.PARSE_CONFIGURATION)) { return; } // 递归处理配置类和其所有父类 SourceClass sourceClass = asSourceClass(configClass, filter); do { sourceClass = doProcessConfigurationClass(configClass, sourceClass, filter); } while (sourceClass != null); }
5.doProcessConfigurationClass方法分析
protected final SourceClass doProcessConfigurationClass( ConfigurationClass configClass, SourceClass sourceClass, Predicatefilter) throws IOException { // 判断配置类上的注解层次中是否包含@Component注解,如果包含则递归获取内部类进行处理 if (configClass.getMetadata().isAnnotated(Component.class.getName())) { // 递归处理所有的内部类 processMemberClasses(configClass, sourceClass, filter); } // 处理配置类上注解层次中的所有@PropertySource注解 for (AnnotationAttributes propertySource : AnnotationConfigUtils.attributesForRepeatable( sourceClass.getMetadata(), PropertySources.class, org.springframework.context.annotation.PropertySource.class)) { if (this.environment instanceof ConfigurableEnvironment) { processPropertySource(propertySource); } else { logger.info("Ignoring @PropertySource annotation on [" + sourceClass.getMetadata().getClassName() + "]. Reason: Environment must implement ConfigurableEnvironment"); } } // 处理配置类上注解层次中的所有@ComponentScan注解 Set componentScans = AnnotationConfigUtils.attributesForRepeatable( sourceClass.getMetadata(), ComponentScans.class, ComponentScan.class); if (!componentScans.isEmpty() && !this.conditionEvaluator.shouldSkip(sourceClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN)) { for (AnnotationAttributes componentScan : componentScans) { // The config class is annotated with @ComponentScan -> perform the scan immediately Set scannedBeanDefinitions = this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName()); // Check the set of scanned definitions for any further config classes and parse recursively if needed for (BeanDefinitionHolder holder : scannedBeanDefinitions) { BeanDefinition bdCand = holder.getBeanDefinition().getOriginatingBeanDefinition(); if (bdCand == null) { bdCand = holder.getBeanDefinition(); } if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) { parse(bdCand.getBeanClassName(), holder.getBeanName()); } } } } // 处理配置类上注解层次中的所有@Import注解 processImports(configClass, sourceClass, getImports(sourceClass), filter, true); // 处理配置类上注解层次中的所有@ImportResource注解 AnnotationAttributes importResource = AnnotationConfigUtils.attributesFor(sourceClass.getMetadata(), ImportResource.class); if (importResource != null) { 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); } } // 处理配置类中的所有标注了@Bean注解的方法,并封装成BeanMethod添加到配置类的实体ConfigurationClass中 Set beanMethods = retrieveBeanMethodMetadata(sourceClass); for (MethodMetadata methodMetadata : beanMethods) { configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass)); } // Process default methods on interfaces processInterfaces(configClass, sourceClass); // 如果有父类,则返回父类 if (sourceClass.getMetadata().hasSuperClass()) { String superclass = sourceClass.getMetadata().getSuperClassName(); if (superclass != null && !superclass.startsWith("java") && !this.knownSuperclasses.containsKey(superclass)) { this.knownSuperclasses.put(superclass, configClass); // Superclass found, return its annotation metadata and recurse return sourceClass.getSuperClass(); } } // 没有父类,返回null return null; }
6.ConfigurationClassBeanDefinitionReader.loadBeanDefinitions方法分析
public void loadBeanDefinitions(SetconfigurationModel) { // 可跟踪记录的条件评估者,也就是解析@Conditon注解的作用,并且可以记录满足@Condition和不满足@Condition的原因 TrackedConditionEvaluator trackedConditionEvaluator = new TrackedConditionEvaluator(); for (ConfigurationClass configClass : configurationModel) { // 从配置类中加载组件定义信息 loadBeanDefinitionsForConfigurationClass(configClass, trackedConditionEvaluator); } } private void loadBeanDefinitionsForConfigurationClass(ConfigurationClass configClass, TrackedConditionEvaluator trackedConditionEvaluator) { // 处理配置类上的@Condition注解 if (trackedConditionEvaluator.shouldSkip(configClass)) { String beanName = configClass.getBeanName(); if (StringUtils.hasLength(beanName) && this.registry.containsBeanDefinition(beanName)) { this.registry.removeBeanDefinition(beanName); } this.importRegistry.removeImportingClass(configClass.getMetadata().getClassName()); return; } // 判断当前配置类是否是通过@Import注解导入的 if (configClass.isImported()) { registerBeanDefinitionForImportedConfigurationClass(configClass); } // 获取配置类中的所有@Bean注解标注的方法 for (BeanMethod beanMethod : configClass.getBeanMethods()) { // 从@Bean标注的方法加载组件定义信息 loadBeanDefinitionsForBeanMethod(beanMethod); } loadBeanDefinitionsFromImportedResources(configClass.getImportedResources()); loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars()); }
7.ConfigurationClassBeanDefinitionReader.loadBeanDefinitionsForBeanMethod方法分析
private void loadBeanDefinitionsForBeanMethod(BeanMethod beanMethod) { // 获取配置类信息 ConfigurationClass configClass = beanMethod.getConfigurationClass(); MethodMetadata metadata = beanMethod.getMetadata(); // 获取方法名 String methodName = metadata.getMethodName(); // 处理方法上的@Conditional注解 if (this.conditionEvaluator.shouldSkip(metadata, ConfigurationPhase.REGISTER_BEAN)) { configClass.skippedBeanMethods.add(methodName); return; } if (configClass.skippedBeanMethods.contains(methodName)) { return; } // 获取方法上@Bean注解的属性信息 AnnotationAttributes bean = AnnotationConfigUtils.attributesFor(metadata, Bean.class); Assert.state(bean != null, "No @Bean annotation attributes"); // 处理@Bean注解的name属性,如果此属性为空,则组件的名称为方法名 Listnames = new ArrayList<>(Arrays.asList(bean.getStringArray("name"))); String beanName = (!names.isEmpty() ? names.remove(0) : methodName); // 将name属性的值注册为此组件的别名 for (String alias : names) { this.registry.registerAlias(beanName, alias); } // 将@Bean方法封装成BeanDefinition ConfigurationClassBeanDefinition beanDef = new ConfigurationClassBeanDefinition(configClass, metadata, beanName); beanDef.setSource(this.sourceExtractor.extractSource(metadata, configClass.getResource())); // 如果@Bean方法为静态方法 if (metadata.isStatic()) { // static @Bean method if (configClass.getMetadata() instanceof StandardAnnotationMetadata) { beanDef.setBeanClass(((StandardAnnotationMetadata) configClass.getMetadata()).getIntrospectedClass()); } else { beanDef.setBeanClassName(configClass.getMetadata().getClassName()); } beanDef.setUniqueFactoryMethodName(methodName); } // 如果@Bean方法为实例方法 else { beanDef.setFactoryBeanName(configClass.getBeanName()); beanDef.setUniqueFactoryMethodName(methodName); } beanDef.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_CONSTRUCTOR); beanDef.setAttribute(org.springframework.beans.factory.annotation.RequiredAnnotationBeanPostProcessor. SKIP_REQUIRED_CHECK_ATTRIBUTE, Boolean.TRUE); /* 处理@Bean方法上的公共注解(@Lazy,@Primary,@DependsOn,@Role,@Description) 这里稍微解释一下这几个注解 @Lazy:组件是否为懒加载,组件的创建可以在项目启动Spring容器刷新的时候创建,也可以在第一次获取组件的时候(BeanFactory.getBean)创建。后者则为懒加载 @Primary:如果一个接口在容器中有多个实现类的时候,在使用@Autowired依赖注入的时候优先使用被@Primary注解标注的实现类 @DependsOn:创建此组件时依赖的其他组件,在创建此组件时,先创建完成依赖的其他组件 @Role:组件的角色,Spring框架底层使用。开发者一般不用 @Description:可以为组件定义添加描述,相当于一个描述信息,仅此而已 */ AnnotationConfigUtils.processCommonDefinitionAnnotations(beanDef, metadata); // 下面一段都是处理@Bean注解的各个属性 Autowire autowire = bean.getEnum("autowire"); if (autowire.isAutowire()) { beanDef.setAutowireMode(autowire.value()); } boolean autowireCandidate = bean.getBoolean("autowireCandidate"); if (!autowireCandidate) { beanDef.setAutowireCandidate(false); } String initMethodName = bean.getString("initMethod"); if (StringUtils.hasText(initMethodName)) { beanDef.setInitMethodName(initMethodName); } String destroyMethodName = bean.getString("destroyMethod"); beanDef.setDestroyMethodName(destroyMethodName); // 将组件定义注册到容器中 this.registry.registerBeanDefinition(beanName, beanDefToRegister); }