1.启动装配入口
XxxxApplication
package com.example.springboot;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
//关键注解, 自动注入的关键
@SpringBootApplication
public class SpringbootApplication {
public static void main(String[] args) {
//run方法, springboot启动入口, 解释注解, 加载配置
SpringApplication.run(SpringbootApplication.class, args);
}
}
2.@SpringBootApplication
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration //标识为配置类
@EnableAutoConfiguration // 启动自动注入配置☆☆☆☆该处为自动装配关键
@ComponentScan(excludeFilters = {
@Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {
//.........省略内容
}
3.@EnableAutoConfiguration
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class) //关键注解, 导入AutoConfigurationImportSelector类, 该类中关键方法org.springframework.boot.autoconfigure.AutoConfigurationImportSelector#selectImports
public @interface EnableAutoConfiguration {
//.........省略内容
}
4.org.springframework.boot.autoconfigure.AutoConfigurationImportSelector#selectImports
@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return NO_IMPORTS;
}
AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader
.loadMetadata(this.beanClassLoader);
//自动注入的Entry
AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(
autoConfigurationMetadata, annotationMetadata);
return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
}
org.springframework.boot.autoconfigure.AutoConfigurationImportSelector#getCandidateConfigurations
-->
org.springframework.core.io.support.SpringFactoriesLoader#loadFactoryNames
-->
org.springframework.core.io.support.SpringFactoriesLoader#loadSpringFactories
private static Map> loadSpringFactories(@Nullable ClassLoader classLoader) {
MultiValueMap result = cache.get(classLoader);
if (result != null) {
return result;
}
try {
//加载自动装配类所处位置FACTORIES_RESOURCE_LOCATION --> META-INF/spring.factories
Enumeration urls = (classLoader != null ?
classLoader.getResources(FACTORIES_RESOURCE_LOCATION) :
ClassLoader.getSystemResources(FACTORIES_RESOURCE_LOCATION));
result = new LinkedMultiValueMap<>();
while (urls.hasMoreElements()) {
URL url = urls.nextElement();
UrlResource resource = new UrlResource(url);
Properties properties = PropertiesLoaderUtils.loadProperties(resource);
for (Map.Entry, ?> entry : properties.entrySet()) {
String factoryClassName = ((String) entry.getKey()).trim();
for (String factoryName : StringUtils.commaDelimitedListToStringArray((String) entry.getValue())) {
result.add(factoryClassName, factoryName.trim());
}
}
}
cache.put(classLoader, result);
return result;
}
catch (IOException ex) {
throw new IllegalArgumentException("Unable to load factories from location [" +
FACTORIES_RESOURCE_LOCATION + "]", ex);
}
}
5.META-INF/spring.factories
自动装配的类全名
# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\
org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration,\
org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration,\
org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration,\
org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration,\
org.springframework.boot.autoconfigure.cloud.CloudServiceConnectorsAutoConfiguration,\
org.springframework.boot.autoconfigure.context.ConfigurationPropertiesAutoConfiguration,\
org.springframework.boot.autoconfigure.context.MessageSourceAutoConfiguration,\
6.不是所有spring.factories的类都加载
例如:
@Configuration
//@ConditionalOnClass 存在这些类才加载, 否则不加载, 没有加入依赖, 以下类都是未导入的
@ConditionalOnClass({ MongoClient.class, com.mongodb.client.MongoClient.class,
MongoTemplate.class })
@Conditional(AnyMongoClientAvailable.class)
@EnableConfigurationProperties(MongoProperties.class)
@Import(MongoDataConfiguration.class)
@AutoConfigureAfter(MongoAutoConfiguration.class)
public class MongoDataAutoConfiguration {
private final MongoProperties properties;
public MongoDataAutoConfiguration(MongoProperties properties) {
this.properties = properties;
}
@Bean
@ConditionalOnMissingBean(MongoDbFactory.class)
public MongoDbFactorySupport> mongoDbFactory(ObjectProvider mongo,
ObjectProvider mongoClient) {
MongoClient preferredClient = mongo.getIfAvailable();
if (preferredClient != null) {
return new SimpleMongoDbFactory(preferredClient,
this.properties.getMongoClientDatabase());
}
com.mongodb.client.MongoClient fallbackClient = mongoClient.getIfAvailable();
if (fallbackClient != null) {
return new SimpleMongoClientDbFactory(fallbackClient,
this.properties.getMongoClientDatabase());
}
throw new IllegalStateException("Expected to find at least one MongoDB client.");
}
//......省略内容