Spring Boot: @SpringBootApplication注解干了个啥?

389 阅读1分钟

@SpringBootApplication注解干了个啥?

通常使用Spring Boot的应用程序的主类是这样的:

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class DemoApplication {

	public static void main(String[] args) {
		SpringApplication.run(DemoApplication.class, args);
	}
}

@SpringBootApplication注解的定义:

@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
		@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {
   ....
}

@SpringBootApplication注解从它的定义能看出来,是一个组合注解,做了三件事情:

  • @SpringBootConfiguration
  • @EnableAutoConfiguration
  • @ComponentScan

第一件事情:@SpringBootConfiguration

@SpringBootConfiguration注解同@Configuration,表明这个类可提供Spring Boot应用配置,也就是在这个类中可定义@Bean注解修饰的方法,这些Bean会由Spring容器管理。比如:

@SpringBootApplication
public class DemoApplication {

	public static void main(String[] args) {
		SpringApplication.run(DemoApplication.class, args);
	}

	@Bean
	public RestTemplate restTemplate() {
		var requestFactory = new OkHttp3ClientHttpRequestFactory();
		return new RestTemplate(requestFactory);
	}
}

这样restTemplate就是一个被Spring容器管理的Bean了。

第二件事情:@EnableAutoConfiguration

很明显,从名字就能看出来,@EnableAutoConfiguration是用来启用自动配置的。当启用Spring应用上下文的自动配置后,Spring Boot会尝试推测需要哪些Bean,并配置这些Bean。自动配置会基于应用的classpath及自定义的Bean来配置。 比如, 如果classpath里包含tomcat-embedded.jar,会自动配置TomcatServletWebServerFactory Bean。

第三件事情:@ComponentScan

不带参数的@ComponentScan告诉Spring扫描当前包及其所有子包。所以@SpringBootApplication所修饰的主类理应放在最外层包,以保证其下的所有@Component都能被扫描到。

当然也可以通过修改@ComponentScan的basePackages来指定扫描的包,如下:

@ComponentScan(basePackages = "chengco.validation.demo")

使用了@SpringBootApplication之后,@ComponentScan注解已经封装在内部了,所以@SpringBootApplication也提供了scanBasePackages和scanBasePackageClasses来完成相应的功能,比如:

@SpringBootApplication(scanBasePackages = { "chengco.validation.demo" })
public class DemoApplication {

	public static void main(String[] args) {
		SpringApplication.run(DemoApplication.class, args);
	}

	@Bean
	public RestTemplate restTemplate() {
		var requestFactory = new OkHttp3ClientHttpRequestFactory();
		return new RestTemplate(requestFactory);
	}
}