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项目,一般会把入口类放在顶层目录中,这样就能够保证源码目录下的所有类都能够被扫描到。
网友评论