一.概要
首先我们都知道所有的springboot的程序的入口都是有一个@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"
)
Class<?>[] exclude() default {};
...........
...........
...........
}
他复合的核心注解主要有以下下面几个:@SpringBootConfiguration、@EnableAutoConfiguration、
@ComponentScan,我们来一个个的去分析这些注解吧。
1.@SpringBootConfiguration:通过观察源码,我们会发现,他是来源于@Configuration注解,他们两者之间的功能也是一样的,就是讲一个类标志为一个配置类,在这个配置类下面,可以有一个或者多个@Bean
2.@ComponentScan:很明显他是表明他扫描的包的
3.@EnableAutoConfiguration:他是自动配置的核心的注解,接下来,我们需要核心的去分析这个注解。
分析@EnableAutoConfiguration
首先,他的源码如下:
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import({EnableAutoConfigurationImportSelector.class})
public @interface EnableAutoConfiguration {
String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";
Class<?>[] exclude() default {};
String[] excludeName() default {};
}
@Import注解
@Import注解可以将一个普通的java类标志为一个Bean
@Import({EnableAutoConfigurationImportSelector.class})导入了类EnableAutoConfigurationImportSelector,在EnableAutoConfigurationImportSelector中,使用loadFactoryNames方法加载自动配置类路径,源码如下:
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
List<String> configurations = SpringFactoriesLoader.loadFactoryNames(this.getSpringFactoriesLoaderFactoryClass(), this.getBeanClassLoader());
Assert.notEmpty(configurations, "No auto configuration classes found in META-INF/spring.factories. If you are using a custom packaging, make sure that file is correct.");
return configurations;
}
一个实现了自动配置的例子:
@Configuration
@ConditionalOnClass({ RabbitTemplate.class, Channel.class })
@EnableConfigurationProperties(RabbitProperties.class)
@Import(RabbitAnnotationDrivenConfiguration.class)
public class RabbitAutoConfiguration {
@Configuration
@ConditionalOnMissingBean(ConnectionFactory.class)
protected static class RabbitConnectionFactoryCreator {
@Bean
public CachingConnectionFactory rabbitConnectionFactory(RabbitProperties config)
throws Exception {
RabbitConnectionFactoryBean factory = new RabbitConnectionFactoryBean();
//......
return connectionFactory;
}
}
//......
}