@ConfigurationProperties(prefix = “spring.datasource”)
public class DataSourceProperties implements BeanClassLoaderAware, InitializingBean {
private ClassLoader classLoader;
private String name;
private boolean generateUniqueName;
private Class extends DataSource> type;
private String driverClassName;
private String url;
private String username;
private String password;
private String jndiName;
。。。
}
配置文件中的属性:
spring:
datasource:
driver-class-name:
url:
password:
username:
前缀+属性名称,如果可以对应上配置文件中的key,就把key对应的value,赋值给bean的属性。这个注解可以单独使用,但你想把这个类放入到容器中,就要搭配@Configuration。注意;这个的搭配和前面两个注解的搭配不一样。@PropertySource,@ComponentScans,如果不和@Configuration注解一起使用,那么其功能就不能实现。而@ConfigurationProperties注解,搭配@Configuration的目的仅仅是将其放入到容器中。如果单独使用功能是可以实现的。 为了方便,springboot还提供了一个注解,EnableConfigurationProperties,这个注解可以将配置的属性bean放入的容器中。
@EnableConfigurationProperties
这个注解可以把属性bean放入到容器中,将处理ConfigurationProperties注解的逻辑类放入到容器中。
@EnableConfigurationProperties(JdbcProperties.class)
public class JdbcTemplateAutoConfiguration {
直接看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 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
for (DeferredImportSelectorHolder deferredImport : this.deferredImports) {
// 这块是从配置文件中读取出配置类(注意,这里的配置类是过滤之后的,过滤逻辑可以可以自己看看),
this.group.process(deferredImport.getConfigurationClass().getMetadata(),
deferredImport.getImportSelector());
}
//
return this.group.selectImports();
}
public Iterable selectImports() {
if (this.autoConfigurationEntries.isEmpty()) {
return Collections.emptyList();
}
Set allExclusions = this.autoConfigurationEntries.stream()
.map(AutoConfigurationEntry::getExclusions).flatMap(Collection::stream).collect(Collectors.toSet());
Set 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 getInPriorityOrder(Collection classNames) {
AutoConfigurationClasses classes = new AutoConfigurationClasses(this.metadataReaderFactory,
this.autoConfigurationMetadata, classNames);
List orderedClassNames = new ArrayList<>(classNames);
// 默认是按照字母的顺序
Collections.sort(orderedClassNames);
// 之后再按照order的顺序
orderedClassNames.sort((o1,
《一线大厂Java面试题解析+后端开发学习笔记+最新架构讲解视频+实战项目源码讲义》
【docs.qq.com/doc/DSmxTbFJ1cmN1R2dB】 完整内容开源分享
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