由多个注解组合而成
源码部分
@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 {
@SpringBootConfiguration 源码
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Configuration
public @interface SpringBootConfiguration {
}
这里面最主要的注解@Configuration
从Spring3.0,@Configuration用于定义配置类,可替换xml配置文件,被注解的类内部包含有一个或多个被@Bean注解的方法,这些方法将会被AnnotationConfigApplicationContext或AnnotationConfigWebApplicationContext类进行扫描,并用于构建bean定义,初始化Spring容器。
1.1@Configuration源码:
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Configuration {
可以看到@Component
2.说明@Configuration注解下的类也会注册为bean,内部可以依赖注入(Bean能用的东西他都能用)
关于注解@Configuration的资料链接: https://blog.csdn.net/leoxyk/article/details/79800020.
将主配置类所在包及其子包下的所有组件都扫描到spring容器
@EnableAutoConfiguration注解源码
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(EnableAutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {
此注解作用为开启自动配置功能,以前需要配置的东西,springboot会帮我们配置好,@EnableAutoConfiguration告诉springboot开启自动配置功能,这样配置才会生效
这里面有@AutoConfigurationPackage注解,此注解作用为自动配置包
2.1@AutoConfigurationPackage源码
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Import(AutoConfigurationPackages.Registrar.class)
public @interface AutoConfigurationPackage {
}
这个自动配置包的功能主要由@Import(AutoConfigurationPackages.Registrar.class)注解来完成的
@Import属于spring底层的注解,此注解的功能可以为容器中导入组件,要怎么导入组件呢?
演示@Configuration和@Import注解的使用方法
下面有我自己用@Configuration注解写的一个连接mysql数据库的一个配置类,里面用到@import注解来向@Configuration注解下的类添加组件
主配置类
/**
* 该类是一个配置类,作用和bean.xml作用一样
* spring中的新注解
* @Configuration 指定当前类是一个配置类
* @ComponentScan 指定要扫描的包
* 属性:basePackages和value一样
* 作用等同于
* @Bean 用于把当前方法的返回值当做bean对象传入Spring的ioc容器中
* 属性:name 用于指定bean的id,如果不写则默认是当前方法的名称
* 当我们使用注解配置方法时,如果方法有参数,spring框架会去容器中查找有没有可用的bean对象
* 查找方式可Autowired方式是一样的,自动按照类型匹配,先匹配容器中有没有唯一配置的类型
*/
@Configuration
@ComponentScan(basePackages = {"com.haohan"})
@PropertySource(value = "classpath:jdbcConfig.properties")
@Import(value = SpringJdbcConfig.class)
public class SpringConfiguration {
}
由@Import调用的组件配置类
public class SpringJdbcConfig {
@Value("${jdbc.driver}")
private String driver;
@Value("${jdbc.url}")
private String url;
@Value("${jdbc.username}")
private String username;
@Value("${jdbc.password}")
private String password;
@Bean(name = "runner")
@Scope(scopeName = "prototype")
public QueryRunner createQueryRunner(@Qualifier("da1") DataSource dataSource){
return new QueryRunner(dataSource);
}
@Bean(name = "da1")
public ComboPooledDataSource createDataSource(){
ComboPooledDataSource comboPooledDataSource = null;
try {
comboPooledDataSource = new ComboPooledDataSource();
comboPooledDataSource.setDriverClass(driver);
comboPooledDataSource.setJdbcUrl(url);
comboPooledDataSource.setUser(username);
comboPooledDataSource.setPassword(password);
} catch (PropertyVetoException e) {
e.printStackTrace();
}
return comboPooledDataSource;
}
}
由@import注解导入了一个AutoConfigurationPackages.Registrar.class的类
** 2.1.1AutoConfigurationPackages.Registrar.class源码**
@Order(Ordered.HIGHEST_PRECEDENCE)
static class Registrar implements ImportBeanDefinitionRegistrar, DeterminableImports {
@Override
public void registerBeanDefinitions(AnnotationMetadata metadata,
BeanDefinitionRegistry registry) {
register(registry, new PackageImport(metadata).getPackageName());
}
@Override
public Set<Object> determineImports(AnnotationMetadata metadata) {
return Collections.<Object>singleton(new PackageImport(metadata));
}
}
此类为一个静态内部类,其中的registerBeanDefinitions方法的参数AnnotationMetadata metadata为注解源信息标的就是@SpringBootApplication,也就是springboot入口的注解,接下来看里面调用的register方法,的第二个参数,new PackageImports(metadata).getPackageNames().toArray(new String[0]))这里
getPackageNames()获取主配置类的包名
在@AutoConfigurationPackage的下方还有个@Import(AutoConfigurationImportSelector.class),导入哪些组件的选择器
2.2 AutoConfigurationImportSelector.class 源码
@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return NO_IMPORTS;
}
try {
AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader
.loadMetadata(this.beanClassLoader);
AnnotationAttributes attributes = getAttributes(annotationMetadata);
List<String> configurations = getCandidateConfigurations(annotationMetadata,
attributes);
configurations = removeDuplicates(configurations);
configurations = sort(configurations, autoConfigurationMetadata);
Set<String> exclusions = getExclusions(annotationMetadata, attributes);
checkExcludedClasses(configurations, exclusions);
configurations.removeAll(exclusions);
configurations = filter(configurations, autoConfigurationMetadata);
fireAutoConfigurationImportEvents(configurations, exclusions);
return configurations.toArray(new String[configurations.size()]);
}
catch (IOException ex) {
throw new IllegalStateException(ex);
}
}
在AutoConfigurationImportSelector有个 selectImports方法,这个方法的作用就是为spring容器导入哪些组件
里面的getCandidateConfigurations方法返回一个configurations的list集合.这个集合里面就是springboot需要导入的组件(自动配置类),比如我们要aop功能,就会导入aop的组件,如果是批处理的功能,就会导入批处理的组件,有了这些自动配置类,就免去了我们手动配置,编写注入功能组件等工作
在spring-boot-autoconfigure包下的/META-INF/spring.factories下获取EnableAutoConfiguration指定的值,将这些值作为自动配置类导入到spring容器中,帮我们进行配置工作