关于springboot的启动类
在我们构建好一个springboot的项目后,我们可以看到一个springboot的启动类,大概是这个样子的。
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
从代码中可以我们可以看到这个启动类中也就两行代码。但是浓缩的往往都是精华。
@SpringBootApplication注解
@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}
)}
)
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
从源码中我们可以看到主要是三个注解在起作用
@ComponentScan
@EnableAutoConfiguration
@SpringBootConfiguration
@ComponentScan
源码
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
@Documented
@Repeatable(ComponentScans.class)
public @interface ComponentScan {
........
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
这个注解的作用是 指定扫描包的位置 如果没有制定,那么会默认是该类同级目录下的所有包
@EnableAutoConfiguration
源码
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import({AutoConfigurationImportSelector.class})
public @interface EnableAutoConfiguration {
String ENABLED_OVERRIDE_PROPERTY = "";
Class<?>[] exclude() default {};
String[] excludeName() default {};
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
该注解也是一个复合注解,其作用主要是:开启自动配置
如何开启自动配置
从源码中我们看到有个注解——@Import({})
这个注解加载了AutoConfigurationImportSelector 类,类中的selectImports方法,根据返回的String数组(配置类的Class的名称)加载配置类。
到这里可能会有一个疑问,Import只是导入了这个类,但是并没有调用
selectImports这个方法,那么是如何加载配置类的呢?主要是在run的方法中调用了selectImports方法。
如果我们继续往下会发现加载的并不是只有我们指定扫描包下的类,也会有其他的类,那么其他的类是如何加载的呢?
#loadSpringFactories 源码
private static Map<String, List<String>> loadSpringFactories(ClassLoader classLoader) {
Map<String, List<String>> result = (Map)cache.get(classLoader);
if (result != null) {
return result;
} else {
HashMap result = new HashMap();
try {
Enumeration urls = classLoader.getResources("META-INF/");
。。。。。。。。。
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
其他的类主要是通过 META-INF/ 这个文件来加载到springboot的容器中的。
@SpringBootConfiguration
源码
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Configuration
@Indexed
public @interface SpringBootConfiguration {
@AliasFor(
annotation = Configuration.class
)
boolean proxyBeanMethods() default true;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
该注解与 @Configuration注解的作用是一致的,也就是标记当前的类为配置类,当前类下如果有@Bean之类的注解,也会被加载到springboot的容器中。
总结
@springBootApplication注解是一个复合注解,主要有三个注解发挥了作用
@ComponentScan 指定扫描包
@EnableAutoConfiguration 加载配置类
@SpringBootConfiguration 标记当前类为配置类
后续有时间,会把源码仔细的肝一遍,了解的更加清楚。有兴趣的朋友可以关注我,一起肝