启动SpringBoot,需要在入口函数所在的类上添加@SpringBootApplication注解
1 @SpringBootApplication
2 public class Application {
3 public static void main(String[] args) {
4 SpringApplication.run(Application.class, args);
5 }
6 }
我们来看一下@SpringBootApplication注解
1 @Target(ElementType.TYPE)
2 @Retention(RetentionPolicy.RUNTIME)
3 @Documented
4 @Inherited
5 @SpringBootConfiguration
6 @EnableAutoConfiguration
7 @ComponentScan(excludeFilters = {
8 @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
9 @Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
10 public @interface SpringBootApplication {
11 @AliasFor(annotation = EnableAutoConfiguration.class, attribute = "exclude")
12 Class<?>[] exclude() default {};
13
14 @AliasFor(annotation = EnableAutoConfiguration.class, attribute = "excludeName")
15 String[] excludeName() default {};
16
17 @AliasFor(annotation = ComponentScan.class, attribute = "basePackages")
18 String[] scanBasePackages() default {};
19
20 @AliasFor(annotation = ComponentScan.class, attribute = "basePackageClasses")
21 Class<?>[] scanBasePackageClasses() default {};
22 }
1 @Target(ElementType.TYPE)
2 @Retention(RetentionPolicy.RUNTIME)
3 @Documented
4 @Configuration
5 public @interface SpringBootConfiguration {
6 }
从上面的代码可以看出@SpringBootApplication = @Configuration + @EnableAutoConfiguration + @ComponentScan
@Configuration注解(可以理解为xml里面的<beans>标签),一般和@Bean注解(可以理解为xml里面的<bean>标签)搭配使用。使用这2个注解可以创建一个配置类,示例如下
1 @Configuration
2 public class Config {
3 @Bean
4 public People people() {
5 People people = new People();
6 people.setAge(26);
7 people.setName("Dylan");
8 people.setGender(1);
9 return people;
10 }
11 }
可以替代xml配置文件里
1 <beans>
2 <bean id="people" class="com.dylan.java.beans.People">
3 <property name="age" value="26"></property>
4 <property name="name" value="Dylan"></property>
5 <property name="gender" value="1"></property>
6 </bean>
7 </beans>
@EnableAutoConfiguration注解自动载入应用程序所需要的所有Bean,这依赖于SpringBoot在类路径中的查找
1 @SuppressWarnings("deprecation")
2 @Target(ElementType.TYPE)
3 @Retention(RetentionPolicy.RUNTIME)
4 @Documented
5 @Inherited
6 @AutoConfigurationPackage
7 @Import(EnableAutoConfigurationImportSelector.class)
8 public @interface EnableAutoConfiguration {
9 String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";
10
11 Class<?>[] exclude() default {};
12
13 String[] excludeName() default {};
14 }
@EnableAutoConfiguration注解使用@Import注解导入EnableAutoConfigurationImportSelector类,此类继承了AutoConfigurationImportSelector类,而AutoConfigurationImportSelector类的selectImports方法就是关键所在
1 @Override
2 public String[] selectImports(AnnotationMetadata annotationMetadata) {
3 if (!isEnabled(annotationMetadata)) {
4 return NO_IMPORTS;
5 }
6 try {
7 AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader
8 .loadMetadata(this.beanClassLoader);
9 AnnotationAttributes attributes = getAttributes(annotationMetadata);
10 List<String> configurations = getCandidateConfigurations(annotationMetadata,
11 attributes);
12 configurations = removeDuplicates(configurations);
13 configurations = sort(configurations, autoConfigurationMetadata);
14 Set<String> exclusions = getExclusions(annotationMetadata, attributes);
15 checkExcludedClasses(configurations, exclusions);
16 configurations.removeAll(exclusions);
17 configurations = filter(configurations, autoConfigurationMetadata);
18 fireAutoConfigurationImportEvents(configurations, exclusions);
19 return configurations.toArray(new String[configurations.size()]);
20 }
21 catch (IOException ex) {
22 throw new IllegalStateException(ex);
23 }
24 }
1 protected List<String> getCandidateConfigurations(AnnotationMetadata metadata,
2 AnnotationAttributes attributes) {
3 List<String> configurations = SpringFactoriesLoader.loadFactoryNames(
4 getSpringFactoriesLoaderFactoryClass(), getBeanClassLoader());
5 Assert.notEmpty(configurations,
6 "No auto configuration classes found in META-INF/spring.factories. If you "
7 + "are using a custom packaging, make sure that file is correct.");
8 return configurations;
9 }
1 protected Class<?> getSpringFactoriesLoaderFactoryClass() {
2 return EnableAutoConfiguration.class;
3 }
可以看出,该方法使用了Spring Core包的SpringFactoriesLoader类的loadFactoryNames方法,该方法会查询classpath下的JAR文件中包含的/META/spring.factories文件,从文件中读取配置文件名(这里是org.springframework.boot.autoconfigure.EnableAutoConfiguration)的属性,例如
在jar:file:/C:/Users/guiqingqing/.m2/repository/org/springframework/boot/spring-boot-autoconfigure/1.5.6.RELEASE/spring-boot-autoconfigure-1.5.6.RELEASE.jar!/META-INF/spring.factories文件找到如下配置
# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\
org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration,\
org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration,\
org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration,\
org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration,\
org.springframework.boot.autoconfigure.cloud.CloudAutoConfiguration,\
org.springframework.boot.autoconfigure.context.ConfigurationPropertiesAutoConfiguration,\
org.springframework.boot.autoconfigure.context.MessageSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration,\
org.springframework.boot.autoconfigure.couchbase.CouchbaseAutoConfiguration,\
org.springframework.boot.autoconfigure.dao.PersistenceExceptionTranslationAutoConfiguration,\
org.springframework.boot.autoconfigure.data.cassandra.CassandraDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.cassandra.CassandraRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.couchbase.CouchbaseDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.couchbase.CouchbaseRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchAutoConfiguration,\
org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.jpa.JpaRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.ldap.LdapDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.ldap.LdapRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.mongo.MongoDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.mongo.MongoRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.neo4j.Neo4jDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.neo4j.Neo4jRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.solr.SolrRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration,\
org.springframework.boot.autoconfigure.data.redis.RedisRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.rest.RepositoryRestMvcAutoConfiguration,\
org.springframework.boot.autoconfigure.data.web.SpringDataWebAutoConfiguration,\
org.springframework.boot.autoconfigure.elasticsearch.jest.JestAutoConfiguration,\
org.springframework.boot.autoconfigure.freemarker.FreeMarkerAutoConfiguration,\
org.springframework.boot.autoconfigure.gson.GsonAutoConfiguration,\
org.springframework.boot.autoconfigure.h2.H2ConsoleAutoConfiguration,\
org.springframework.boot.autoconfigure.hateoas.HypermediaAutoConfiguration,\
org.springframework.boot.autoconfigure.hazelcast.HazelcastAutoConfiguration,\
org.springframework.boot.autoconfigure.hazelcast.HazelcastJpaDependencyAutoConfiguration,\
org.springframework.boot.autoconfigure.info.ProjectInfoAutoConfiguration,\
org.springframework.boot.autoconfigure.integration.IntegrationAutoConfiguration,\
org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.JndiDataSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.XADataSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration,\
org.springframework.boot.autoconfigure.jms.JmsAutoConfiguration,\
org.springframework.boot.autoconfigure.jmx.JmxAutoConfiguration,\
org.springframework.boot.autoconfigure.jms.JndiConnectionFactoryAutoConfiguration,\
org.springframework.boot.autoconfigure.jms.activemq.ActiveMQAutoConfiguration,\
org.springframework.boot.autoconfigure.jms.artemis.ArtemisAutoConfiguration,\
org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration,\
org.springframework.boot.autoconfigure.groovy.template.GroovyTemplateAutoConfiguration,\
org.springframework.boot.autoconfigure.jersey.JerseyAutoConfiguration,\
org.springframework.boot.autoconfigure.jooq.JooqAutoConfiguration,\
org.springframework.boot.autoconfigure.kafka.KafkaAutoConfiguration,\
org.springframework.boot.autoconfigure.ldap.embedded.EmbeddedLdapAutoConfiguration,\
org.springframework.boot.autoconfigure.ldap.LdapAutoConfiguration,\
org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration,\
org.springframework.boot.autoconfigure.mail.MailSenderAutoConfiguration,\
org.springframework.boot.autoconfigure.mail.MailSenderValidatorAutoConfiguration,\
org.springframework.boot.autoconfigure.mobile.DeviceResolverAutoConfiguration,\
org.springframework.boot.autoconfigure.mobile.DeviceDelegatingViewResolverAutoConfiguration,\
org.springframework.boot.autoconfigure.mobile.SitePreferenceAutoConfiguration,\
org.springframework.boot.autoconfigure.mongo.embedded.EmbeddedMongoAutoConfiguration,\
org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration,\
org.springframework.boot.autoconfigure.mustache.MustacheAutoConfiguration,\
org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration,\
org.springframework.boot.autoconfigure.reactor.ReactorAutoConfiguration,\
org.springframework.boot.autoconfigure.security.SecurityAutoConfiguration,\
org.springframework.boot.autoconfigure.security.SecurityFilterAutoConfiguration,\
org.springframework.boot.autoconfigure.security.FallbackWebSecurityAutoConfiguration,\
org.springframework.boot.autoconfigure.security.oauth2.OAuth2AutoConfiguration,\
org.springframework.boot.autoconfigure.sendgrid.SendGridAutoConfiguration,\
org.springframework.boot.autoconfigure.session.SessionAutoConfiguration,\
org.springframework.boot.autoconfigure.social.SocialWebAutoConfiguration,\
org.springframework.boot.autoconfigure.social.FacebookAutoConfiguration,\
org.springframework.boot.autoconfigure.social.LinkedInAutoConfiguration,\
org.springframework.boot.autoconfigure.social.TwitterAutoConfiguration,\
org.springframework.boot.autoconfigure.solr.SolrAutoConfiguration,\
org.springframework.boot.autoconfigure.thymeleaf.ThymeleafAutoConfiguration,\
org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration,\
org.springframework.boot.autoconfigure.transaction.jta.JtaAutoConfiguration,\
org.springframework.boot.autoconfigure.validation.ValidationAutoConfiguration,\
org.springframework.boot.autoconfigure.web.DispatcherServletAutoConfiguration,\
org.springframework.boot.autoconfigure.web.EmbeddedServletContainerAutoConfiguration,\
org.springframework.boot.autoconfigure.web.ErrorMvcAutoConfiguration,\
org.springframework.boot.autoconfigure.web.HttpEncodingAutoConfiguration,\
org.springframework.boot.autoconfigure.web.HttpMessageConvertersAutoConfiguration,\
org.springframework.boot.autoconfigure.web.MultipartAutoConfiguration,\
org.springframework.boot.autoconfigure.web.ServerPropertiesAutoConfiguration,\
org.springframework.boot.autoconfigure.web.WebClientAutoConfiguration,\
org.springframework.boot.autoconfigure.web.WebMvcAutoConfiguration,\
org.springframework.boot.autoconfigure.websocket.WebSocketAutoConfiguration,\
org.springframework.boot.autoconfigure.websocket.WebSocketMessagingAutoConfiguration,\
org.springframework.boot.autoconfigure.webservices.WebServicesAutoConfiguration
获取自动配置的类之后调用removeDuplicates方法先去除重复,然后调用sort方法进行排序,接下来调用getExclusions方法获取配置的exclude的类,比如@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class}),然后这些exclude的类也会被排除
然后是调用filter方法,该方法决定哪些bean自动配置,哪些不配置。去classpath下的JAR文件中包含的/META/spring.factories文件里查询org.springframework.boot.autoconfigure.AutoConfigurationImportFilter对应的配置,这里找到的是org.springframework.boot.autoconfigure.condition.OnClassCondition,检查规则如下
经过上面的去重,排序,排除,(这里会有2个线程分别对前一半和后一半做检查)遍历所有剩下的class
首先看是否有@ConditionalOnClass注解,如果没有那么不过滤,表示需要配置这个bean
如果有@ConditionalOnClass注解,再看这个注解依赖的类是否为空,如果为空,那么也不过滤,表示需要配置这个bean
如果@ConditionalOnClass注解依赖的类不为空,那么再看classpath下能不能找到这个依赖的类,如果能找到,那么也不过滤,表示需要配置这个bean,否则过滤,表示不配置这个bean
例如FreeMarkerAutoConfiguration类
1 @Configuration
2 @ConditionalOnClass({ freemarker.template.Configuration.class, FreeMarkerConfigurationFactory.class })
4 @AutoConfigureAfter(WebMvcAutoConfiguration.class)
5 @EnableConfigurationProperties(FreeMarkerProperties.class)
6 public class FreeMarkerAutoConfiguration {
7 }
该类的@ConditionalOnClass注解里有freemarker.template.Configuration.class和FreeMarkerConfigurationFactory.class类,如果classpath下能找到这2个类,那么就会自动加载FreeMarkerAutoConfiguration类
最后去classpath下的JAR文件中包含的/META/spring.factories文件里查询org.springframework.boot.autoconfigure.AutoConfigurationImportListener对应的属性作为监听器,然后发布一个AutoConfigurationImportEvent事件
最后交代一下,selectImports方法的调用时机,是在SpringBoot启动时,AbstractApplicationContext类refresh方法 -> invokeBeanFactoryPostProcessors方法 -> PostProcessorRegistrationDelegate类的invokeBeanFactoryPostProcessors方法 -> invokeBeanDefinitionRegistryPostProcessors方法 -> ConfigurationClassPostProcessor类的postProcessBeanDefinitionRegistry方法 -> processConfigBeanDefinitions方法 -> ConfigurationClassParser类的parse方法 -> processDeferredImportSelectors方法
1 private void processDeferredImportSelectors() {
2 List<DeferredImportSelectorHolder> deferredImports = this.deferredImportSelectors;
3 this.deferredImportSelectors = null;
4 Collections.sort(deferredImports, DEFERRED_IMPORT_COMPARATOR);
5
6 for (DeferredImportSelectorHolder deferredImport : deferredImports) {
7 ConfigurationClass configClass = deferredImport.getConfigurationClass();
8 try {
9 String[] imports = deferredImport.getImportSelector().selectImports(configClass.getMetadata());
10 processImports(configClass, asSourceClass(configClass), asSourceClasses(imports), false);
11 }
12 catch (BeanDefinitionStoreException ex) {
13 throw ex;
14 }
15 catch (Throwable ex) {
16 throw new BeanDefinitionStoreException(
17 "Failed to process import candidates for configuration class [" +
18 configClass.getMetadata().getClassName() + "]", ex);
19 }
20 }
21 }
@ComponentScan注解会自动扫描指定包(如果不指定,那么默认扫描当前类路径以及子路径下的所有类)下的全部标有@Component(包括@Service、@Repository、@Controller等子注解)的类,并注册成bean