1前言
Spring Boot 项目都会自动生成一个启动类,可以运行启动类的 main 方法来启动一个 Spring Boot 项目。
@SpringBootApplication
public class TestApplication {
public static void main(String[] args) {
SpringApplication.run(TestApplication.class, args);
}
}
我们发现,在我们的启动类上自动添加了一个注解 @SpringBootApplication,那么到底这个注解有什么作用呢?让我们一起走进 Spring Boot 的源码吧。
2 @SpringBootApplication 分析
/**
* Indicates a {@link Configuration configuration} class that declares one or more
* {@link Bean @Bean} methods and also triggers {@link EnableAutoConfiguration
* auto-configuration} and {@link ComponentScan component scanning}. This is a convenience
* annotation that is equivalent to declaring {@code @Configuration},
* {@code @EnableAutoConfiguration} and {@code @ComponentScan}.
*
* @author Phillip Webb
* @author Stephane Nicoll
* @since 1.2.0
*/
@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 {
/**
* Exclude specific auto-configuration classes such that they will never be applied.
* @return the classes to exclude
*/
@AliasFor(annotation = EnableAutoConfiguration.class)
Class<?>[] exclude() default {};
/**
* Exclude specific auto-configuration class names such that they will never be
* applied.
* @return the class names to exclude
* @since 1.3.0
*/
@AliasFor(annotation = EnableAutoConfiguration.class)
String[] excludeName() default {};
/**
* Base packages to scan for annotated components. Use {@link #scanBasePackageClasses}
* for a type-safe alternative to String-based package names.
* @return base packages to scan
* @since 1.3.0
*/
@AliasFor(annotation = ComponentScan.class, attribute = "basePackages")
String[] scanBasePackages() default {};
/**
* Type-safe alternative to {@link #scanBasePackages} for specifying the packages to
* scan for annotated components. The package of each class specified will be scanned.
* <p>
* Consider creating a special no-op marker class or interface in each package that
* serves no purpose other than being referenced by this attribute.
* @return base packages to scan
* @since 1.3.0
*/
@AliasFor(annotation = ComponentScan.class, attribute = "basePackageClasses")
Class<?>[] scanBasePackageClasses() default {};
}
我们可以看到,@SpringBootApplication 提供了四个可配置项:
- exclude:根据类排除不使用的自动配置
- excludeName:根据类名排除不使用的自动配置
- scanBasePackages:扫描指定的包
- scanBasePackageClasses:扫描指定的类
同时 @SpringBootApplication 注解组合了@SpringBootConfiguration 注解 、@EnableAutoConfiguration 注解和@ComponentScan 注解,故我们可以直接使用 @SpringBootConfiguration ,@EnableAutoConfiguration ,@ComponentScan 来代替 @SpringBootApplication。
3 @SpringBootConfiguration 源码分析
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Configuration
public @interface SpringBootConfiguration {
}
@SpringBootConfiguration 与 @Configuration 作用大致相同,标注当前类为配置类,并将当前类内声明的一个或多个以 @Bean 注解标记的方法的实例纳入到 spring 容器中。
4 @EnableAutoConfiguration 源码分析
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {
String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";
/**
* Exclude specific auto-configuration classes such that they will never be applied.
* @return the classes to exclude
*/
Class<?>[] exclude() default {};
/**
* Exclude specific auto-configuration class names such that they will never be
* applied.
* @return the class names to exclude
* @since 1.3.0
*/
String[] excludeName() default {};
}
@EnableAutoConfiguration 借助 @Import 的帮助,将所有符合自动配置条件的 bean 加载到 IoC 容器。
我们看到上面有这么一行代码:
@Import(AutoConfigurationImportSelector.class)
其作用为通过使用 AutoConfigurationImportSelector ,将所有符合条件的 @Configuration 配置都加载到当前 SpringBoot 项目的 IoC 容器。
5 @ComponentScan 源码分析
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Repeatable(ComponentScans.class)
public @interface ComponentScan {
//省略部分代码
}
@ComponentScan 的功能为自动扫描并加载符合条件的组件(比如 @Component),最终将这些 bean 加载到 IoC 容器中。在不指定参数的时候,@ComponentScan 默认会扫描同目录及同目录下级目录的类文件,也可以通过 basePackages 来控制 @ComponentScan 自动扫描的范围。