1. Spring Boot 入口——main方法
@SpringBootApplication
public class Application {
public static void main(String[] args) throws Exception {
SpringApplication.run(Application.class, args);
}
}
從上面代碼可以看出,Annotation定義(@SpringBootApplication)和類定義(SpringApplication.run)最爲耀眼,所以分析 Spring Boot 啓動過程,我們就從這兩位開始。
2. 核心註解
2.1 @SpringBootApplication
@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}.
* 標示一個聲明有一個或多個的@Bean方法的Configuration類並且觸發自動配置(EnableAutoConfiguration)
* 和組建掃描(ComponentScan)。
* 這是一個相當於@Configuration、@EnableAutoConfiguration、@ComponentScan 三合一的組合註解。
*/
@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")
Class<?>[] exclude() default {};
@AliasFor(annotation = EnableAutoConfiguration.class, attribute = "excludeName")
String[] excludeName() default {};
@AliasFor(annotation = ComponentScan.class, attribute = "basePackages")
String[] scanBasePackages() default {};
@AliasFor(annotation = ComponentScan.class, attribute = "basePackageClasses")
Class<?>[] scanBasePackageClasses() default {};
}
從源碼聲明可以看出,@SpringBootApplication相當於 @SpringBootConfiguration + @EnableAutoConfiguration + @ComponentScan ,因此我們直接拆開來分析。
2.2 @SpringBootConfiguration
@SpringBootConfiguration 是繼承自Spring的 @Configuration 註解,@SpringBootConfiguration 作用相當於 @Configuration。
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Configuration
public @interface SpringBootConfiguration {
}
spring 3.0中增加了@Configuration,@Bean。可基於JavaConfig形式對 Spring 容器中的bean進行更直觀的配置。SpringBoot推薦使用基於JavaConfig的配置形式。
基於xml配置:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"
default-lazy-init="true">
<bean id="mockService" class="..MockServiceImpl">
...
</bean>
</beans>
基於JavaConfig配置:
@Configuration
public class MockConfiguration{
@Bean
public MockService mockService(){
return new MockServiceImpl();
}
}
總結,@Configuration相當於一個spring的xml文件,配合@Bean註解,可以在裏面配置需要Spring容器管理的bean。
2.3 @ComponentScan
@ComponentScan源碼:
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Repeatable(ComponentScans.class)
public @interface ComponentScan {
/**
* 對應的包掃描路徑 可以是單個路徑,也可以是掃描的路徑數組
* @return
*/
@AliasFor("basePackages")
String[] value() default {};
/**
* 和value一樣是對應的包掃描路徑 可以是單個路徑,也可以是掃描的路徑數組
* @return
*/
@AliasFor("value")
String[] basePackages() default {};
/**
* 指定具體的掃描類
* @return
*/
Class<?>[] basePackageClasses() default {};
/**
* 對應的bean名稱的生成器 默認的是BeanNameGenerator
* @return
*/
Class<? extends BeanNameGenerator> nameGenerator() default BeanNameGenerator.class;
/**
* 處理檢測到的bean的scope範圍
*/
Class<? extends ScopeMetadataResolver> scopeResolver() default AnnotationScopeMetadataResolver.class;
/**
* 是否爲檢測到的組件生成代理
*/
ScopedProxyMode scopedProxy() default ScopedProxyMode.DEFAULT;
/**
* 控制符合組件檢測條件的類文件 默認是包掃描下的
* @return
*/
String resourcePattern() default ClassPathScanningCandidateComponentProvider.DEFAULT_RESOURCE_PATTERN;
/**
* 是否對帶有@Component @Repository @Service @Controller註解的類開啓檢測,默認是開啓的
* @return
*/
boolean useDefaultFilters() default true;
/**
* 指定某些定義Filter滿足條件的組件
* @return
*/
Filter[] includeFilters() default {};
/**
* 排除某些過來器掃描到的類
* @return
*/
Filter[] excludeFilters() default {};
/**
* 掃描到的類是都開啓懶加載 ,默認是不開啓的
* @return
*/
boolean lazyInit() default false;
}
基於xml配置:
<context:component-scan base-package="com.youzan" use-default-filters="false">
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
基於JavaConfig配置:
@Configuration
@ComponentScan(value = "com.youzan", excludeFilters = {
@ComponentScan.Filter(type = FilterType.ANNOTATION, classes = {Controller.class})
})
public class ScanConfig {
}
總結:@ComponentScan通常與@Configuration一起配合使用,相當於xml裏面的<context:component-scan>
,用來告訴Spring需要掃描哪些包或類。如果不設值的話默認掃描@ComponentScan註解所在類的同級類和同級目錄下的所有類,所以對於一個Spring Boot項目,一般會把入口類放在頂層目錄中,這樣就能夠保證源碼目錄下的所有類都能夠被掃描到。