)原理
直接看EnableConfigurationPropertiesImportSelector
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Import(EnableConfigurationPropertiesImportSelector.class) public @interface EnableConfigurationProperties {
org.springframework.boot.context.properties.EnableConfigurationPropertiesImportSelector
实现了ImportSelector接口,直接看selectImports方法
private static final String[] IMPORTS = { ConfigurationPropertiesBeanRegistrar.class.getName(), ConfigurationPropertiesBindingPostProcessorRegistrar.class.getName() }; @Override public String[] selectImports(AnnotationMetadata metadata) { return IMPORTS; }
返回了两个类ConfigurationPropertiesBeanRegistrar是将配置的属性bean放入到容器。ConfigurationPropertiesBindingPostProcessorRegistrar是处理ConfigurationProperties注解的,绑定逻辑。这两个类的逻辑自己看就可以了,了解大概流程。
[](
)@NestedConfigurationProperty
这个注解还是和属性相关,是嵌套类型的。使用方法[使用方法](
),解析的逻辑应该还是在ConfigurationPropertiesBindingPostProcessorRegistrar类中。
[](
)@ImportResource
这个类是加载配置文件的,没有springboot之前,使用spring的时候要有spring.xml的文件,在里面陪各种信息。这个注解就是加载xml配置文件的。
下面重点分析条件注解
[](
)AutoConfigureBefore、AutoConfigureAfter、AutoConfigureOrder
在自动配置的时候,会找到这三个注解,注意,这三个注解是springboot自动配置专用的注解,我们开发的时候是用不上的。主要功能就是区分解析的的顺序,
org.springframework.context.annotation.ConfigurationClassParser.DeferredImportSelectorGroupingHandler#processGroupImports
public void processGroupImports() { for (DeferredImportSelectorGrouping grouping : this.groupings.values()) { Predicate<String> exclusionFilter = grouping.getCandidateFilter(); // 得到所有的配置类,之后遍历 grouping.getImports().forEach(entry -> { ConfigurationClass configurationClass = this.configurationClasses.get(entry.getMetadata()); try { // 分别调用processImports,走导入类的逻辑。 processImports(configurationClass, asSourceClass(configurationClass, exclusionFilter), Collections.singleton(asSourceClass(entry.getImportClassName(), exclusionFilter)), exclusionFilter, false); } catch (BeanDefinitionStoreException ex) { throw ex; } catch (Throwable ex) { throw new BeanDefinitionStoreException( "Failed to process import candidates for configuration class [" + configurationClass.getMetadata().getClassName() + "]", ex); } }); } }
下面看看grouping.getImports()方法做了什么操作。
public Iterable<Group.Entry> getImports() { for (DeferredImportSelectorHolder deferredImport : this.deferredImports) { // 这块是从配置文件中读取出配置类(注意,这里的配置类是过滤之后的,过滤逻辑可以可以自己看看), this.group.process(deferredImport.getConfigurationClass().getMetadata(), deferredImport.getImportSelector()); } // return this.group.selectImports(); }
public Iterable
if (this.autoConfigurationEntries.isEmpty()) { return Collections.emptyList(); } Set<String> allExclusions = this.autoConfigurationEntries.stream() .map(AutoConfigurationEntry::getExclusions).flatMap(Collection::stream).collect(Collectors.toSet()); Set<String> processedConfigurations = this.autoConfigurationEntries.stream() .map(AutoConfigurationEntry::getConfigurations).flatMap(Collection::stream) .collect(Collectors.toCollection(LinkedHashSet::new)); processedConfigurations.removeAll(allExclusions); // 这步,排序了,看看是怎么排序的 return sortAutoConfigurations(processedConfigurations, getAutoConfigurationMetadata()).stream() .map((importClassName) -> new Entry(this.entries.get(importClassName), importClassName)) .collect(Collectors.toList()); }
List<String> getInPriorityOrder(Collection<String> classNames) { AutoConfigurationClasses classes = new AutoConfigurationClasses(this.metadataReaderFactory, this.autoConfigurationMetadata, classNames); List<String> orderedClassNames = new ArrayList<>(classNames); // 默认是按照字母的顺序 Collections.sort(orderedClassNames); // 之后再按照order的顺序 orderedClassNames.sort((o1, o2) -> { int i1 = classes.get(o1).getOrder(); int i2 = classes.get(o2).getOrder(); return Integer.compare(i1, i2); }); // 之后处理@AutoConfigureBefore @AutoConfigureAfter注解的配置。 orderedClassNames = sortByAnnotation(classes, orderedClassNames); return orderedClassNames; } ``` []( )ConditionalOnClass,ConditionalOnBean,ConditionalOnMissingBean,ConditionalOnMissingClass,ConditionalOnProperty ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 这些都是属于同一类的,都是过滤配置类的条件。**首先要明白我们自己的配置类是先放入到org.springframework.context.annotation.ConfigurationClassParser#configurationClasses中的,之后才是自动配置类。** org.springframework.context.annotation.ConfigurationClassParser#processConfigurationClass ``` protected void processConfigurationClass(ConfigurationClass configClass, Predicate<String> filter) throws IOException { // 在这步进行条件判断,符合的才会继续解析。 if (this.conditionEvaluator.shouldSkip(configClass.getMetadata(), ConfigurationPhase.PARSE_CONFIGURATION)) { return; } 。。。 ``` 进入方法。 遍历每一个条件类,如果不匹配,就返回true,跳过该配置类,不再解析。 ``` for (Condition condition : conditions) { ConfigurationPhase requiredPhase = null; if (condition instanceof ConfigurationCondition) { requiredPhase = ((ConfigurationCondition) condition).getConfigurationPhase(); } ### 笔者福利 ##### 以下是小编自己针对马上即将到来的金九银十准备的一套“面试宝典”,不管是技术还是HR的问题都有针对性的回答。 **有了这个,面试踩雷?不存在的!** ##### **[CodeChina开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频】](https://ali1024.coding.net/public/P7/Java/git)** ##### 回馈粉丝,诚意满满!!! ![](https://upload-images.jianshu.io/upload_images/13465705-035ef7d211a21fd9.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) ![](https://upload-images.jianshu.io/upload_images/13465705-aebe8fb4f0c3988a.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) ![](https://upload-images.jianshu.io/upload_images/13465705-e2eae2d6f4a6aa76.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) ![](https://upload-images.jianshu.io/upload_images/13465705-5fb970f18a184658.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)