一、介绍一下@SpringBootApplication 注解
先看下SpringBootApplication注解代码
package org.springframework.boot.autoconfigure;
@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 {
........
}
package org.springframework.boot;
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Configuration
public @interface SpringBootConfiguration {
}
由上面代码可以看出@SpringBootApplication是@Configuration、@EnableAutoConfiguration、@ComponentScan注解的集合。根据SpringBoot官网的解释,这三个注解的作用分别是:
- @EnableAutoConfiguration: 启动SpringBoot的自动配置机制
- @ComponentScan: 扫描被@Component (@Service,@Controller)注解的bean,注解默认会扫描该类所在的包下所有类。
- @Configuration: 允许再上下文中注册额外的bean或导入其他配置类
二、Spring Boot的自动配置是如何实现的
这个是因为@SpringBootApplication注解的原因,在上一个问题中已经提到了这个注解,我们知道@SpringBootApplication是@Configuration、@EnableAutoConfiguration、@Component注解的集合。
@EnableAutoConfiguration是启动自动配置的关键,源码如下(建议自己打断点调试,走一遍基本的流程):
package org.springframework.boot.autoconfigure;
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import({AutoConfigurationImportSelector.class})
public @interface EnableAutoConfiguration {
String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";
Class<?>[] exclude() default {};
String[] excludeName() default {};
}
@EnableAutoConfiguration注解通过Spring提供的@Import注解导入了AutoConfigurationImportSelector类(@Import 注解可以导入配置类或者Bean到当前类中)。
AutoConfigurationImportSelector类中getCandidateConfigurations方法会将所有自动配置类的信息以List的形式返回。这些配置信息会被Spring容器作bean来管理。
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
List<String> configurations = SpringFactoriesLoader.loadFactoryNames(this.getSpringFactoriesLoaderFactoryClass(), this.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;
}
以上获取到了自动配置信息,然后就是哦通过@Conditional注解。
@ConditionalOnClass(指定的类必须存在于类路径下),@ConditionalOnBean(容器中是否有指定的Bean)等等都是对@Conditional注解的扩展。
拿Spring Security的自动配置举个例子:SecurityAutoConfiguration中导入了WebSecurityEnablerConfiguration类, WebSecurityEnablerConfiguration源代码如下:
package org.springframework.boot.autoconfigure.security.servlet;
@Configuration
@ConditionalOnBean({WebSecurityConfigurerAdapter.class})
@ConditionalOnMissingBean(
name = {"springSecurityFilterChain"}
)
@ConditionalOnWebApplication(
type = Type.SERVLET
)
@EnableWebSecurity
public class WebSecurityEnablerConfiguration {
public WebSecurityEnablerConfiguration() {
}
}
WebSecurityEnablerConfiguration类中使用@ConditionalOnBean指定了容器中必须还有WebSecurityConfigurerAdapter 类或其实现类。所有,一般情况下Spring Security 配置类都会去实现WebSecurityConfigurerAdapter,这样自动将配置就完成了。
以上便是SpringBoot自动配置的大致实现流程。