- pom.xml
spring-boot-starter-parent:从字面上来理解,这属于导入了一个父项目
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.9.RELEASE</version>
</parent>
点击进入spring-boot-starter-parent会发现,还依赖了一个父项目spring-boot-dependencies
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>1.5.9.RELEASE</version>
<relativePath>../../spring-boot-dependencies</relativePath>
</parent>
点击进入spring-boot-dependencies会发现下面有一个< Dependency versions >,这里包含了Spring Boot 的所有依赖版本,所以称为Spring Boot 的版本控制中心,既然如此,那就是说,以后我们导入依赖默认是不需要写版本的;除不在dependencies中管理的依赖,则需要声明依赖版本
<properties>
<!-- Dependency versions -->
<activemq.version>5.14.5</activemq.version>
<antlr2.version>2.7.7</antlr2.version>
<appengine-sdk.version>1.9.59</appengine-sdk.version>
<artemis.version>1.5.5</artemis.version>
<aspectj.version>1.8.13</aspectj.version>
</properties>
- starter(启动器)
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
spring-boot-starter-web:字面意思理解spring-boot-starter为场景启动器,点进spring-boot-starter-web会发现其中有一个,其中可以很明确的看出,spring-boot-starter-web说明他依赖于spring-boot-starter场景启动器,往下看到,有依赖很多其他的依赖,如spring-boot-starter-tomcat,到这里就很明白,为什么单独的一个web应用不需要发布到服务器中就能启动起来,这里依赖的版本都受到spring-boot-dependencies的版本控制,在官方文档中,我们可以看到很多场景启动器,我们只需要针对自己开发的需要去导入对应的启动器就可以了,Spring Boot将所有的功能场景都抽取出来,做成了一个个的starter(启动器)所以说只需要在项目中引入这些启动器
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</dependency>
.......等
- @SpringBootApplication注解(Spring Boot应用程序)
@SpringBootApplication标注在某个类上,就说明这个类是Spring Boot的主程序类(主配置类),点击进入@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}
)}
)
public @interface SpringBootApplication {
@AliasFor(
annotation = EnableAutoConfiguration.class,
attribute = "exclude"
@SpringBootConfiguration:Spring Boot 配置类,他标注在某个类上表示是一个Spring Boot的配置类,点击进入会发现里面有一个@Configuration,这里就是Spring的底层注解了,这里的配置类,就是之前所说的配置文件,之前大量的配置文件,在这里由配置类完成,配置类也属于容器中的一个组件
@EnableAutoConfiguration:开启自动配置,进去@AutoConfigurationPackage:自动配置包(属于组合注解)进入@AutoConfigurationPackage会发现有一个@Import({Registrar.class})的注解,这里也是spring的底层注解,他的作用就是给容器中导入组件由Registrar.class来控制,进入这个类会看到registerBeanDefinitions()这个方法,这里的AutoConfigurationPackages.PackageImport(metadata)).getPackageName()顾名思义就是拿到包的名字,将主配置类所在的包下面的所有组件都扫描到容器中去,所以主配置类的位置要慎重慎重再慎重,所以说@Import({EnableAutoConfigurationImportSelector.class})的意思就是给容器中导入一些组件,其中要导入哪些组件,就由EnableAutoConfigurationImportSelector.class(开启自动配置类的选择器)类来控制,将所有需要导入的组件以全类名的方式放回,添加到容器中,会给容器导入很多的自动配置类,这些作用就是给容器中导入这个场景所需要的所有组件,并配置好
public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
AutoConfigurationPackages.register(registry, (new AutoConfigurationPackages.PackageImport(metadata)).getPackageName());
}
public String[] selectImports(AnnotationMetadata annotationMetadata) {
if (!this.isEnabled(annotationMetadata)) {
return NO_IMPORTS;
} else {
try {
AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader.loadMetadata(this.beanClassLoader);
AnnotationAttributes attributes = this.getAttributes(annotationMetadata);
List<String> configurations = this.getCandidateConfigurations(annotationMetadata, attributes);
configurations = this.removeDuplicates(configurations);
configurations = this.sort(configurations, autoConfigurationMetadata);
Set<String> exclusions = this.getExclusions(annotationMetadata, attributes);
this.checkExcludedClasses(configurations, exclusions);
configurations.removeAll(exclusions);
configurations = this.filter(configurations, autoConfigurationMetadata);
this.fireAutoConfigurationImportEvents(configurations, exclusions);
return (String[])configurations.toArray(new String[configurations.size()]);
} catch (IOException var6) {
throw new IllegalStateException(var6);
}
}
}
这里可以看到META-INF/spring.factories,所以说,Spring Boot在启动时从类路径下的META-INF/spring.factories中获取EnableAutoConfigurationImportSelector指定的值,把这些值作为自动配置类导入到容器中,配置类就生效,进行自动配置
public static List<String> loadFactoryNames(Class<?> factoryClass, ClassLoader classLoader) {
String factoryClassName = factoryClass.getName();
try {
Enumeration<URL> urls = classLoader != null ? classLoader.getResources("META-INF/spring.factories") : ClassLoader.getSystemResources("META-INF/spring.factories");
ArrayList result = new ArrayList();
while(urls.hasMoreElements()) {
URL url = (URL)urls.nextElement();
Properties properties = PropertiesLoaderUtils.loadProperties(new UrlResource(url));
String factoryClassNames = properties.getProperty(factoryClassName);
result.addAll(Arrays.asList(StringUtils.commaDelimitedListToStringArray(factoryClassNames)));
}