配置关键类和注解
关于@EnableAutoConfiguration
首先,@EnableAutoConfiguration注解是@SpringBootApplication注解的一部分,顾名思义,在启动类上面标注@SpringBootApplication会自动开启自动配置。
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(...)
public @interface SpringBootApplication{
...
}
SpringFactoriesLoader.class
开启自动配置后,在SpringBoot项目启动时,就会加载SpringFactoriesLoader.class的loadSpringFactories方法。方法中有一句代码:getResources("META-INF/spring.factories") ,也就是说,我们未配置的东西SpringBoot都会在META-INF/spring.factories中去加载。
private static Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader) {
MultiValueMap<String, String> result = (MultiValueMap)cache.get(classLoader);
if (result != null) {
return result;
} else {
try {
Enumeration<URL> urls = classLoader != null ? classLoader.getResources("META-INF/spring.factories") : ClassLoader.getSystemResources("META-INF/spring.factories");
LinkedMultiValueMap result = new LinkedMultiValueMap();
while(urls.hasMoreElements()) {
URL url = (URL)urls.nextElement();
UrlResource resource = new UrlResource(url);
Properties properties = PropertiesLoaderUtils.loadProperties(resource);
Iterator var6 = properties.entrySet().iterator();
while(var6.hasNext()) {
Entry<?, ?> entry = (Entry)var6.next();
String factoryClassName = ((String)entry.getKey()).trim();
String[] var9 = StringUtils.commaDelimitedListToStringArray((String)entry.getValue());
int var10 = var9.length;
for(int var11 = 0; var11 < var10; ++var11) {
String factoryName = var9[var11];
result.add(factoryClassName, factoryName.trim());
}
}
}
cache.put(classLoader, result);
return result;
} catch (IOException var13) {
throw new IllegalArgumentException("Unable to load factories from location [META-INF/spring.factories]", var13);
}
}
}
AutoConfiguration结尾的类
ServletWebServerFactoryAutoConfiguration的类注解上有两个比较关键的注解@Configuration、@ConditionalOnClass()。其中@Configuration大家都比较熟悉,标注这个类就是配置类;而@ConditionalOnClass()则说明该配置类只在ServletRequest.class存在时才会加载进Spring。
因此,我们可以知道,SpringBoot内置了大量的AutoConfiguration结尾的类,这些类写好了如何配置一些属性。
@Configuration
@AutoConfigureOrder(-2147483648)
@ConditionalOnClass({ServletRequest.class})
@ConditionalOnWebApplication(...)
@EnableConfigurationProperties({ServerProperties.class})
@Import(...)
public class ServletWebServerFactoryAutoConfiguration {
...
}
Properties结尾的类
承接上一小节,ServletWebServerFactoryAutoConfiguration会把配置内容配置到ServletRequest中,这是由@ConditionalOnClass()控制的。ServletRequest的类注解@ConfigurationProperties表明了server前缀的配置可以配置进该类的对应属性。
那么,已经很明显了,ServletWebServerFactoryAutoConfiguration用来启动对应的配置类,最终server开头的配置信息会进入到ServerProperties的port属性。也就是我们常常配置的server.port=80。
@ConfigurationProperties(
prefix = "server",
ignoreUnknownFields = true
)
public class ServerProperties {
private Integer port;
//...
}
也就是说Properties结尾的类是SpringBoot为我们提前准备好,接受自定义配置的类。
@ConditionalOn开头的注解
上文提到了和@Configuration一起工作的注解,也就是那些@ConditionalOn开头的注解。这些注解常常作用在AutoConfiguration结尾的类上,用来限制这些配置类,这类注解还有:
@ConditionalOnBean:当容器里有指定的bean的条件下。
@ConditionalOnMissingBean:当容器里不存在指定bean的条件下。
@ConditionalOnClass:当类路径下有指定类的条件下。
@ConditionalOnMissingClass:当类路径下不存在指定类的条件下。
@ConditionalOnProperty:指定的属性是否有指定的值,比如@ConditionalOnProperties(prefix=”xxx.xxx”, value=”enable”, matchIfMissing=true),代表当xxx.xxx为enable时条件的布尔值为true,如果没有设置的情况下也为true。
小结
Spring Boot启动的时候会通过@EnableAutoConfiguration注解找到META-INF/spring.factories配置文件中的所有自动配置类,并对其进行加载,而这些自动配置类都是以AutoConfiguration结尾来命名的,它实际上就是一个JavaConfig形式的Spring容器配置类,它能通过以Properties结尾命名的类中取得在全局配置文件中配置的属性如:server.port,而XxxxProperties类是通过@ConfigurationProperties注解与全局配置文件中对应的属性进行绑定的。
评论区