
1、springboot启动类:
package com.sourcecode.helloworld;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class HelloworldApplication {
public static void main(String[] args) {
SpringApplication.run(HelloworldApplication.class, args);
}
}
@SpringBootApplication 注解标志了这是一个springboot应用
2、SpringBootApplication注解源码
该注解又包含了两个配置注解:
@SpringBootConfiguration 注解标志了springboot配置
@EnableAutoConfiguration 注解标志了启动springboot自动配置
- 2-1、SpringBootConfiguration注解源码
该注解又包含了一个配置注解:
@Configuration 注解标志了这是一个配置
- 2-1-1、Configuration注解源码:
@Component 注解标志了这个注解可被spring扫描到
- 2-2、EnableAutoConfiguration注解源码
该注解又包含了两个注解:
@AutoConfigurationPackage 注解标志自动配置包
@Import(AutoConfigurationImportSelector.class) 注解导入自动配置选择器
- 2-2-1、AutoConfigurationPackage注解源码
该注解又包含了一个注解:
@Import(AutoConfigurationPackages.Registrar.class) 注解导入自动配置包注册器
- 2-2-1-1、Registrar类源码
- 2-2-2、AutoConfigurationImportSelector类源码:
核心方法:
/**
* 返回应考虑的自动配置类名。默认情况下 * 这个方法将使用{@link SpringFactoriesLoader}加载候选对象 * {@link # getSpringFactoriesLoaderFactoryClass()}。 * @param metadata源元数据 * @param attributes {@link #getAttributes(AnnotationMetadata)注释 * 属性} * 返回候选配置的列表
*/
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
List<String> configurations = SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(),
getBeanClassLoader());
Assert.notEmpty(configurations, "No auto configuration classes found in META-INF/spring.factories. If you "
+ "are using a custom packaging, make sure that file is correct.");
return configurations;
}
- getSpringFactoriesLoaderFactoryClass()方法内容:
/**
*返回{@link SpringFactoriesLoader}用于加载配置的类 *候选人。 *返回工厂类
*/
protected Class<?> getSpringFactoriesLoaderFactoryClass() {
return EnableAutoConfiguration.class;
}
这意味着标注了这个类的都将在启动的时候被加载
回过头来看SpringBootApplication注解源码,就标注了这个注解启动时就会被加载:
- SpringFactoriesLoader.loadFactoryNames()方法内容:
/**
类的工厂实现的完全限定类名 {@value #FACTORIES_RESOURCE_LOCATION},使用给定类型 *类装入器。 * 从Spring Framework 5.3开始,如果一个特定的实现类名 对于给定的工厂类型,会多次发现重复的工厂类型 *被忽略。 表示工厂的接口或抽象类 用于加载资源的类加载器;可以 * {@code null}使用默认值 * @throws IllegalArgumentException,如果在加载工厂名称时发生错误 * @see # loadFactories
*/
public static List<String> loadFactoryNames(Class<?> factoryType, @Nullable ClassLoader classLoader) {
ClassLoader classLoaderToUse = classLoader;
if (classLoaderToUse == null) {
classLoaderToUse = SpringFactoriesLoader.class.getClassLoader();
}
String factoryTypeName = factoryType.getName();
return loadSpringFactories(classLoaderToUse).getOrDefault(factoryTypeName, Collections.emptyList());
}
String factoryTypeName = factoryType.getName(); 获取工厂类型名
- loadSpringFactories(ClassLoader classLoader) 方法内容:
其中FACTORIES_RESOURCE_LOCATION 为 META-INF/spring.factories 文件
/**
* The location to look for factories.
* <p>Can be present in multiple JAR files.
*/
public static final String FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories";
META-INF/spring.factories内容:
存放着所有的自动配置类,全部都加载到上面loadSpringFactories(ClassLoader classLoader) 方法中的properties配置类中,但并不一定会生效,必须满足自动配置类的生效条件
如mvc自动配置类:
满足这些条件才会生效!